我有一个程序通过Sql Alchemy ORM运行以下查询。在代码中的这个特定点,它是串行运行的。
//ms sql database setup
engine = create_engine(conn_string, pool_size=pool_size, pool_recycle=3600, echo=False)
engine.execute('set transaction isolation level read uncommitted')
session = scoped_session(sessionmaker(bind=engine, autocommit=autocommit))
//hangs in here
max_id = session.query(func.max(entity.entity_id)).all()[0][0]
有时,程序会挂起,就像它已经死锁一样。执行不会持续数小时。我排除了数据库连接或阻塞查询中的任何问题,因为我的主调用线程的定期堆栈跟踪显示执行挂在以下位置(请参阅下面的StackTrace)。
似乎字典正在更新。如果SqlAlchemy试图对引擎盖下的线程做任何事情,weakref.py
使用来自https://docs.python.org/3/library/weakref.html#weakref.WeakValueDictionary的WeakValueDictionary
,其中self.data
是本地python字典应该是在并发访问下安全。
导致这种间歇性挂起的原因是什么?我正在使用SQL Alchemy 1.0.12
和Python 3.5.2
。
File "/home/me/py35/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2588, in all
return list(self)
File "/home/me/py35/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2732, in __iter__
context = self._compile_context()
File "/home/me/py35/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 3180, in _compile_context
if self.dispatch.before_compile:
File "/home/me/py35/lib/python3.5/site-packages/sqlalchemy/event/base.py", line 288, in __get__
obj.__dict__['dispatch'] = disp = self.dispatch_cls._for_instance(obj)
File "/home/me/py35/lib/python3.5/site-packages/sqlalchemy/event/base.py", line 110, in _for_instance
return self._for_class(instance_cls)
File "/home/me/py35/lib/python3.5/site-packages/sqlalchemy/event/base.py", line 106, in _for_class
return self.__class__(self, instance_cls)
File "/home/me/py35/lib/python3.5/site-packages/sqlalchemy/event/base.py", line 84, in __init__
for ls in parent._event_descriptors
File "/home/me/py35/lib/python3.5/site-packages/sqlalchemy/event/base.py", line 84, in <genexpr>
for ls in parent._event_descriptors
File "/home/me/py35/lib/python3.5/site-packages/sqlalchemy/event/attr.py", line 188, in __init__
parent.update_subclass(target_cls)
File "/home/me/py35/lib/python3.5/site-packages/sqlalchemy/event/attr.py", line 125, in update_subclass
self._clslevel[target] = collections.deque()
File "/home/me/py35/lib/python3.5/weakref.py", line 378, in __setitem__
self.data[ref(key, self._remove)] = value