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 应用程序中,我遇到如下间歇性错误:
DatabaseError: (psycopg2.DatabaseError) error with no message from the libpq
ResourceClosedError: This result object does not return rows. It has been closed automatically.
NoSuchColumnError: "Could not locate column in row for column 'my_table.my_column_name_that_exists'"
DatabaseError: (psycopg2.DatabaseError) insufficient data in "D" message...lost synchronization with server: got message type "2", length 740303471
在我的 postgresql 日志中,我看到:WARNING: there is already a transaction in progress
在 flask 中刷新网页通常可以解决错误。
以下是我重现错误的步骤:
- 停止应用程序
sudo service postgresql restart
- 启动应用程序
- 导航到我的 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 中解决这个问题,有以下选项:
- 在创建应用程序之前不要创建数据库连接,或
- 使用
--lazy-apps
选项调用 uwsgi,这会在创建应用程序之前将 uwsgi 更改为 fork
lazy-apps
模式(参见 preforking vs lazy-apps vs lazy)会对性能产生负面影响,因此在创建应用程序期间避免使用数据库通常是更好的选择。
感谢 univerio 在评论中对此进行解释。
在我的 UWSGI Flask 应用程序中,我遇到如下间歇性错误:
DatabaseError: (psycopg2.DatabaseError) error with no message from the libpq
ResourceClosedError: This result object does not return rows. It has been closed automatically.
NoSuchColumnError: "Could not locate column in row for column 'my_table.my_column_name_that_exists'"
DatabaseError: (psycopg2.DatabaseError) insufficient data in "D" message...lost synchronization with server: got message type "2", length 740303471
在我的 postgresql 日志中,我看到:WARNING: there is already a transaction in progress
在 flask 中刷新网页通常可以解决错误。
以下是我重现错误的步骤:
- 停止应用程序
sudo service postgresql restart
- 启动应用程序
- 导航到我的 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 中解决这个问题,有以下选项:
- 在创建应用程序之前不要创建数据库连接,或
- 使用
--lazy-apps
选项调用 uwsgi,这会在创建应用程序之前将 uwsgi 更改为 fork
lazy-apps
模式(参见 preforking vs lazy-apps vs lazy)会对性能产生负面影响,因此在创建应用程序期间避免使用数据库通常是更好的选择。
感谢 univerio 在评论中对此进行解释。