gpt4 book ai didi

python - 回滚后"This transaction is closed"

转载 作者:太空宇宙 更新时间:2023-11-03 20:30:26 28 4
gpt4 key购买 nike

我正在尝试在 Pyramid 提供的事务管理器内进行一些架构更改。我在尝试回滚后运行提交时遇到了各种问题:

简化版本是:

def get_version(conn):
try:
result = conn.execute('SELECT version FROM versions LIMIT 1')
return result.scalar()
except:
conn.rollback()
return 0

def m_version_table(conn):
conn.execute('CREATE TABLE versions (version INT)')
conn.execute('INSERT INTO versions VALUES (1)')

def handle(conn):
ver = get_version(conn)
m_version_table(conn)

# task started with pyramid's transaction manager
with env['request'].tm as tm:
handle(env['request'].dbsession)

事务是隐式启动的,我可以在日志中看到:

 BEGIN (implicit)
SELECT version FROM versions LIMIT 1
()
ROLLBACK

BEGIN (implicit)
CREATE TABLE versions (version INT)
()
INSERT INTO versions VALUES (1)
()
UPDATE versions SET version = %s
(1,)
ROLLBACK

如果 versions 存在(并且之后我运行不同的 ALTER),则一切正常。但回滚后,我只是得到:

Traceback (most recent call last):
File ".venv/bin/schema_refresh", line 11, in <module>
load_entry_point('project', 'console_scripts', 'schema_refresh')()
File ".../schema_refresh.py", line 270, in run
handle(env['request'].dbsession, tm)
File ".../transaction-2.4.0-py3.7.egg/transaction/_manager.py", line 140, in __exit__
self.commit()
File ".../transaction-2.4.0-py3.7.egg/transaction/_manager.py", line 131, in commit
return self.get().commit()
...
sqlalchemy.exc.ResourceClosedError: This transaction is closed

为什么回滚后即使已经正确启动了新事务,下一个事务也无法提交? (ROLLBACK 后跟 BEGIN(隐式))

最佳答案

tl;博士
看起来这不是 __exit__ 在您的示例中尝试提交的新事务。
在数据库 session 上调用回滚确实会创建一个新的 session 事务,但它不会与管理器在上下文中跟踪的事务结合在一起。您对 execute 的后续调用是在新 session 事务中完成的,但 commit 是在进入上下文时创建的原始第一个事务上调用的。

<小时/>

假设您使用 cookiecutter 来设置项目,您的 models.__init__.py 可能是 default from the repo .

这意味着 env['request'].tm 返回一个 Zope TransactionManager并且,当进入其上下文时,begin()方法实例化 Transaction对象和 stores it in the _txn attribute .

env['request'].dbsession 返回 SQLAlchemy Session ,之后registering与事务管理器一起使用。
TransactionManagerTransaction 现在是 joinedSessionSessionTransaction并且应该控制它的结局和结果。

在处理 execute() 调用中引发的异常时回滚 SessionTransaction 会绕过事务管理器。调用其 commit()rollback() 方法(稍后由 __exit__ 完成),仍会尝试终止 SessionTransaction 你回滚了。
此外,没有任何机制可以将新事务与管理器连接起来。

您可以使用事务管理器或选择手动事务控制。只要坚持你的选择,不要混合两者。

关于python - 回滚后"This transaction is closed",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57548929/

28 4 0