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

时间:2017-04-06 20:24:15

标签: ruby-on-rails postgresql

我在Rails应用中有自定义PostgreSQL prepared statements的用例(what ActiveRecord does automatically除外)。

我的用例是批量插入一堆行,例如:

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'
);

我无法知道,对于任何给定的执行,是否会显示2行,10行或其他。所以我希望能够做到的是:

  • 如果使用3行调用我的方法,请查看我是否已PREPARE编辑此语句的3行版本。
  • 如果没有,PREPARE
  • EXECUTE

我可以跟踪“我已经准备好了吗?”在应用程序代码中,但我不确定它是否可靠。

PostgreSQL docs say

  

预准备语句仅在当前数据库会话期间持续。会话结束时,忘记了准备好的语句,因此必须重新创建它才能再次使用。这也意味着多个并发数据库客户端不能使用单个预准备语句;但是,每个客户端都可以创建自己准备好的语句来使用。可以使用DEALLOCATE命令手动清除准备语句。

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

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

我有一个原型工作,我只是总是准备语句,总是 DEALLOCATE执行后,但这看起来非常低效。

这一切都可能过于实用,但它至少很有趣。

1 个答案:

答案 0 :(得分:3)

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

  

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

简短的回答:它试图。

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

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

因此,除非连接被关闭(例如手动或PgBouncer),否则您将在整个应用程序生命周期内获得相同的连接。

  

将不同的实例(Unicorn工作进程,Puma线程或其他)视为不同的数据库客户端

流程:是的。

线程:这取决于。并发线程肯定会得到自己的连接,但如果在任何时候只有一个活动线程,那么它们最有可能从池中获得相同的连接。