Mik*_*maa 5 postgresql sqlalchemy zope transactionmanager pyramid
我正在运行Pyramid + Zope事务管理器+ SQLAlchemy + PostgreSQL.在某些情况下,我StaleDataError在Pyramid Web应用程序上看到了错误,这应该是更新数据库中一行的非常简单的视图.由于错误发生在正常视图边界之外且不可重复,因此调试非常棘手.
我想这可能与破坏的数据库连接或事务生命周期有关.但是我不知道如何开始调试系统,所以我问的是什么可能导致这个问题,以及如何解决这样的错误.
UPDATE statement on table 'xxx' expected to update 1 row(s); 0 were matched.
Stacktrace (most recent call last):
File "pyramid/tweens.py", line 20, in excview_tween
response = handler(request)
File "pyramid_tm/__init__.py", line 94, in tm_tween
reraise(*exc_info)
File "pyramid_tm/compat.py", line 15, in reraise
raise value
File "pyramid_tm/__init__.py", line 82, in tm_tween
manager.commit()
File "transaction/_manager.py", line 111, in commit
return self.get().commit()
File "transaction/_transaction.py", line 280, in commit
reraise(t, v, tb)
File "transaction/_compat.py", line 55, in reraise
raise value
File "transaction/_transaction.py", line 271, in commit
self._commitResources()
File "transaction/_transaction.py", line 417, in _commitResources
reraise(t, v, tb)
File "transaction/_compat.py", line 55, in reraise
raise value
File "transaction/_transaction.py", line 389, in _commitResources
rm.tpc_begin(self)
File "/srv/pyramid/trees/venv/lib/python3.4/site-packages/zope/sqlalchemy/datamanager.py", line 90, in tpc_begin
self.session.flush()
File "sqlalchemy/orm/session.py", line 2004, in flush
self._flush(objects)
File "sqlalchemy/orm/session.py", line 2122, in _flush
transaction.rollback(_capture_exception=True)
File "sqlalchemy/util/langhelpers.py", line 60, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "sqlalchemy/util/compat.py", line 182, in reraise
raise value
File "sqlalchemy/orm/session.py", line 2086, in _flush
flush_context.execute()
File "sqlalchemy/orm/unitofwork.py", line 373, in execute
rec.execute(self)
File "sqlalchemy/orm/unitofwork.py", line 532, in execute
uow
File "sqlalchemy/orm/persistence.py", line 170, in save_obj
mapper, table, update)
File "sqlalchemy/orm/persistence.py", line 692, in _emit_update_statements
(table.description, len(records), rows))
Run Code Online (Sandbox Code Playgroud)
这很可能是这种情况:
您有2个请求首先选择一个对象并尝试在数据存储区中更新/删除它,最终会出现"竞争条件".
让我们说你想要做一些事情,比如获取一个对象然后更新它.
如果事务需要一些时间并且您没有选择带有"for update"的对象,从而锁定行 - 如果对象在第一个请求中被删除而第二个事务尝试向db中不存在的行发出更新,那么您可以结束这个例外.
您可以尝试进行一些行锁定以防止这种情况发生 - 后续事务将"等待"第一个操作完成.在它被执行之前.
和
描述一些可用于解决此问题的sqlalchemy机器.
另外一个选择:
TL,DR:如果在某些情况下有“first()”,并且更新多条记录,则需要在炼金术中删除它
db.session.query(xxx).filter_by(field=value).first()
Run Code Online (Sandbox Code Playgroud)
此命令预计更新仅影响一行。如果您的表只有一条带有field=value. 如果该字段是您的 ID,则尤其如此。
但是,如果您的 ID 不唯一,则可能有多个具有相同 ID 的记录。
在这种情况下,您可以通过删除“first()”来更新所有内容
顺便说一句,使用以下命令来调试 SQL 查询(这一次没有帮助......)
import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
Run Code Online (Sandbox Code Playgroud)