UWSGI Flask SQLAlchemy 间歇性 PostgreSQL 错误 "WARNING: there is already a transaction in progress"

UWSGI Flask SQLAlchemy Intermittent PostgreSQL errors with "WARNING: there is already a transaction in progress"

在我的 UWSGI Flask 应用程序中,我遇到如下间歇性错误:

在我的 postgresql 日志中,我看到:WARNING: there is already a transaction in progress

在 flask 中刷新网页通常可以解决错误。

以下是我重现错误的步骤:

  1. 停止应用程序
  2. sudo service postgresql restart
  3. 启动应用程序
  4. 导航到我的 Flask 应用程序中执行多个同时查询的网页
    • 预期行为:没有记录数据库错误
    • 实际行为:出现上面列出的一个或多个错误

我尝试增加 postgresql 日志记录的冗长程度以及虚拟事务共享似乎不合适的内容,例如以下显示了具有虚拟事务 2/53 并对应于上述错误的所有日志条目:

process 8548 session 5901589a.2164 vtransaction 2/53 LOG:  statement: BEGIN
process 8548 session 5901589a.2164 vtransaction 2/53 LOG:  statement: SELECT 1
process 8548 session 5901589a.2164 vtransaction 2/53 LOG:  statement: SELECT my_table.id AS my_table_id, ... 
    FROM my_table 
    WHERE my_table.id = 'my_id' 
     LIMIT 1
process 8548 session 5901589a.2164 vtransaction 2/53 LOG:  statement: BEGIN
process 8548 session 5901589a.2164 vtransaction 2/53 WARNING:  there is already a transaction in progress
process 8548 session 5901589a.2164 vtransaction 2/53 LOG:  statement: SELECT 1
process 8548 session 5901589a.2164 vtransaction 2/53 LOG:  statement: SELECT my_other_table.id AS my_other_table_id, ...
    FROM my_other_table
    WHERE 'my_other_id' = my_other_table.id
process 8548 session 5901589a.2164 vtransaction 2/53 LOG:  statement: SELECT my_table.id AS my_table_id, ... 
    FROM my_table 
    WHERE my_table.id = 'my_id' 
     LIMIT 1
process 8548 session 5901589a.2164 vtransaction 2/53 LOG:  statement: ROLLBACK

这些错误是数据库连接被多个线程或进程错误共享的症状。

默认情况下,uwsgi 在 wsgi 文件中创建应用程序后分叉进程。如果应用程序创建创建了可以重复使用的数据库连接,那么您最终可能会得到数据库状态已损坏的分叉进程。要在 uwsgi 中解决这个问题,有以下选项:

  1. 在创建应用程序之前不要创建数据库连接,
  2. 使用 --lazy-apps 选项调用 uwsgi,这会在创建应用程序之前将 uwsgi 更改为 fork

lazy-apps 模式(参见 preforking vs lazy-apps vs lazy)会对性能产生负面影响,因此在创建应用程序期间避免使用数据库通常是更好的选择。

感谢 univerio 在评论中对此进行解释。