Ada*_*ris 5 python mysql django mod-wsgi sqlalchemy
我最近更新到 SQLAlchemy 1.1,我在 Django 1.10 下使用它(最近也从 1.6 更新),并且我不断收到 sqlalchemy/mysql 错误 This session is in 'prepared' state; no further SQL can be emitted within this transaction.
我该如何调试?
它在 mod_wsgi 下的单进程、多线程环境中运行 - 我不确定我是否正确配置了 SQLAlchemy 的 scoped_session。
我使用分配给每个传入请求的请求容器,它设置会话并清理它。(我假设 Django 中的每个请求都在它自己的线程上。)
# scoped_session as a global variable
# I constant errors if pool_size = 20 for some reason
Engine = create_engine(host, pool_recycle=600, pool_size=10, connect_args=options)
Session = scoped_session(sessionmaker(autoflush=True, bind=Engine))
RUNNING_DEVSERVER = (len(sys.argv) > 1 and sys.argv[1] == 'runserver') # Session.remove() fails in dev
# Created in my API, once per request (per thread)
class RequestContainer(object):
def __init__(self, request, *args, **kwargs):
self.s = Session()
def safe_commit(self):
try:
self.s.commit()
except:
self.s.rollback()
raise
def __del__(self):
if self.s:
try:
self.s.commit()
except:
self.s.rollback()
raise
if not RUNNING_DEVSERVER:
Session.remove()
self.s = None
Run Code Online (Sandbox Code Playgroud)
并且prepared state在代码中弹出错误,通常在同一个地方,但不是一直出现,有时在其他地方:
...
rs = request_container.s.query(MyTable)
...
if rs.count():
# Error log:
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/query.py", line 3011, in count
return self.from_self(col).scalar()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/query.py", line 2765, in scalar
ret = self.one()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/query.py", line 2736, in one
ret = self.one_or_none()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/query.py", line 2706, in one_or_none
ret = list(self)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/query.py", line 2777, in __iter__
return self._execute_and_instances(context)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/query.py", line 2798, in _execute_and_instances
close_with_result=True)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/query.py", line 2807, in _get_bind_args
**kw
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/query.py", line 2789, in _connection_from_session
conn = self.session.connection(**kw)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 903, in connection
execution_options=execution_options)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 908, in _connection_for_bind
engine, execution_options)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 319, in _connection_for_bind
self._assert_active()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.1.0b3-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 201, in _assert_active
"This session is in 'prepared' state; no further "
InvalidRequestError: This session is in 'prepared' state; no further SQL can be emitted within this transaction.
Run Code Online (Sandbox Code Playgroud)
RequestContainer 被意外分配给全局 API 接口处理程序,导致一个会话在多个线程之间被误用,而该会话本来是为每个线程创建的。
更新以显示如何将会话分配给每个线程,包括拆卸以防止数据库提交错误挂起会话状态:
class ThreadSessionRequest(object):
def __init__(self, request, *args, **kwargs):
self.s = Session()
def __del__(self):
if self.s:
self.remove_session()
def remove_session(self):
if self.s:
try:
self.safe_commit()
finally:
Session.remove()
del self.s
self.s = None
def safe_commit(self):
if self.s:
try:
self.s.commit()
except:
self.s.rollback()
raise
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6359 次 |
| 最近记录: |