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

Nat*_*ong 5 postgresql ruby-on-rails

我在Rails应用程序中有自定义PostgreSQL预处理语句的用例(除了ActiveRecord自动执行的操作).

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

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'
);
Run Code Online (Sandbox Code Playgroud)

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

  • 如果我的方法被调用3行,看看我是否已经PREPARE编写了这个语句的3行版本.
  • 如果没有,PREPARE
  • EXECUTE

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

PostgreSQL的文档说:

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

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

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

我有一个原型工作,我总是准备语句,并始终 DEALLOCATE在执行后,但这似乎效率很低.

这一切都可能过于苛刻而不实用,但它至少是有趣的.

Dan*_*ski 4

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

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

简短的回答:它试图这样做。

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

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

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

不同的实例(Unicorn 工作进程、Puma 线程或其他)是否会被视为不同的数据库客户端

流程:是的。

主题:这要看情况。并发线程肯定会获得自己的连接,但如果任何时候都没有超过一个活动线程,那么它们很可能都从池中获得相同的连接。