Rails是否无限期地使用单个“数据库会话”?

问题描述:

我有一个用于定制PostgreSQL prepared statements在Rails应用程序(除了what ActiveRecord does automatically)的用例。Rails是否无限期地使用单个“数据库会话”?

我的使用情况是,以批量插入一串行,如:

PREPARE insert_2_events (text, text, timestamp, int, json, timestamp, timestamp) 
AS 
INSERT INTO events (uuid, kind, generated_at, team_id, data, created_at, updated_at) 
VALUES 
($1, $2, $3, $4, $5, $6, $7), ($8, $9, $10, $11, $12, $13, $14) 
ON CONFLICT(uuid) DO NOTHING; 

EXECUTE insert_2_events(
    'ed8bd52a-4ea9-4548-ab02-87adfca90789', 'call', '2017-04-06T16:14:20-04:00', 1, '{"some":"data"}', '2017-04-06T20:14:20+00:00', '2017-04-06T20:14:20+00:00', 
    '27c3251e-aff0-4005-918a-d7011f984515', 'text', '2017-04-06T16:14:20-04:00', 1, '{awesome:true}', '2017-04-06T20:14:20+00:00', '2017-04-06T20:14:20+00:00' 
); 

我不能知道是否,对于任何给定的执行,会出现如图所示,10行2列,或随你。所以我希望能够做到的是:

  • 如果我的方法被称为3行,看看是否我已经PREPARE编这句话的3行版本。
  • 如果不是,它PREPARE
  • EXECUTE

我可以追踪 “都我已经准备呢?”在应用程序代码中,但我不确定这是可靠的。

PostgreSQL docs say

准备语句仅持续当前数据库会话的持续时间。当会话结束时,准备好的语句被遗忘,所以在重新使用之前必须重新创建。这也意味着一个准备好的语句不能被多个同时使用的数据库客户端使用;不过,每个客户都可以创建自己准备好的声明来使用。已准备好的语句可以使用DEALLOCATE命令手动清理。

我不确定“数据库会话”概念如何映射到Rails应用程序。

  • Rails应用程序在整个运行过程中是否使用相同的数据库会话?
  • 将不同的实例(独角兽工作进程,Puma线程或其他)视为不同的数据库客户端(我认为是这样),在这种情况下,我需要跟踪线程局部变量中已准备好哪些语句?

我有一个工作原型,我只是总是准备语句,并总是DEALLOCATE它执行后,但似乎非常低效。

这一切都可能太实际,但至少有趣。

PostgreSQL和Rails对同一事物使用不同的词:PostgresSQL中的会话对应于Rails中的连接。

Rails应用程序在整个运行过程中是否使用同一个数据库会话?

简答:它试图。

长答案:Rails维护线程安全的pool连接/会话。每次请求都会从池中借用连接,然后返回。

如果没有现有连接,例如在第一次请求或所有活动连接被检出时,Rails会打开一个新连接(直到达到最大连接数)

因此,除非连接关闭(例如手动或通过PgBouncer)在整个应用程序生命周期中,最终会有相同的连接。

将在不同情况下(麒麟工作进程,彪马线程,或其他)被认为是不同的数据库客户

进程:是的。

主题:取决于。并发线程必然会获得自己的连接,但如果任何时候只有一个线程处于活动状态,那么很可能它们都从池中获得相同的连接。

+0

非常有帮助的回答,谢谢! :)听起来像1“数据库会话”是单一连接的生命周期? –

+0

鉴于您描述的连接池策略,检查预准备语句是否存在的唯一有效方法是询问数据库。 –

+1

问题是PostgreSQL和Rails对同一个事物(或多或少)使用不同的词。 PostgresSQL中的* session *对应于Rails中的*连接*。在PostgreSQL会话中与连接密切相关,但原则上可以在没有会话的情况下进行连接,例如, (https://www.postgresql.org/docs/current/static/protocol-flow.html)当然在Rails中,术语“会话”已经用于HTTP会话。 –