使用 SQLAlchemy 查询 PgBouncer 后面的 PostgreSQL 数据库,使用事务级池。
用于这种设置的最佳模式是什么?我应该使用一个每个进程ConnectionPool
一个引擎,还是应该为每个请求创建一个引擎,并NullPool
为它们中的每一个使用?我应该使用完全不同的模式吗?
非常感谢!让我知道是否需要更多信息,我会尽快更新。
使用 SQLAlchemy 查询 PgBouncer 后面的 PostgreSQL 数据库,使用事务级池。
用于这种设置的最佳模式是什么?我应该使用一个每个进程ConnectionPool
一个引擎,还是应该为每个请求创建一个引擎,并NullPool
为它们中的每一个使用?我应该使用完全不同的模式吗?
非常感谢!让我知道是否需要更多信息,我会尽快更新。
使用 PGBouncer,您可能只想坚持使用 NullPool。在这种情况下,您可以跨子进程共享单个引擎,因为不会在子进程边界上传输套接字连接。但是您不能在此边界上共享任何引用 Connection 对象的内容,例如具有活动事务的 Session。但是,您绝对不想执行“每个请求的引擎”,引擎是一个昂贵的对象,它会在第一次看到特定数据库 URL 时积累大量有关特定数据库 URL 的信息。
设置应用程序名称
如果您希望运行许多进程,您需要知道它们从哪里连接。PGBouncer 将使其对
pg_stat_activity
. 通过仔细设置所需application_name
的信息来解决此问题:首选会话
使用会话,因为来自 Engine 对象的请求可以产生并保持多个连接。连接到 Postgres 并不是很昂贵,而使用 PGBouncer 则更便宜。我将始终使用
NullPool
,以便您在 Postgres 中看到的唯一连接是实际使用的连接。消除空闲事务
如果您的意图是使用 PGBouncer 进行扩展,那么您必须避免让交易保持打开状态。为此,您需要
autocommit
打开. 这对 SQLAlchemy 来说并不简单......可以在三个地方设置“自动提交”:psycopg2 自动提交
假定是 unsafe 不安全的,因为 SQLAlchemy 需要知道下面发生了什么。
会话自动提交
这需要仔细、明确的处理:
函数调用和异常处理非常困难,因为
begin()
不能commit()
嵌套:在这种模式下 psycopg2
autocommit
似乎是False
(默认)引擎自动提交
在创建引擎时将引擎隔离模式设置为
"AUTOCOMMIT"
建立新的默认行为,可能不需要更改现有代码。在这种模式下 psycopg2
autocommit
似乎是True
这里的主要问题是,保证代码块包装在事务中的唯一方法是手动发出语句: