【发布时间】:2014-08-19 18:53:28
【问题描述】:
从IntegrityError 或任何其他可能导致我的交易在不使用手动交易控制的情况下搞砸的错误中恢复的正确方法是什么?
在我的应用程序中,我遇到了我想从中恢复的 IntegrityErrors 问题,这会破坏以后的数据库活动,让我有:
DatabaseError: current transaction is aborted, commands ignored until end of transaction block`
忽略IntegrityErrors后的所有数据库活动。
这段代码应该会重现我看到的错误
from django.db import transaction
try:
MyModel.save() # Do a bad save that will raise IntegrityError
except IntegrityError:
pass
MyModel.objects.all() # raises DatabaseError: current transaction is aborted, commands ignored until end of transaction block
根据the docs,从IntegrityError 恢复的解决方案是回滚事务。但是下面的代码会生成TransactionManagementError。
from django.db import transaction
try:
MyModel.save()
except IntegrityError:
transaction.rollback() # raises TransactionManagementError: This code isn't under transaction management
MyModel.objects.all() # Should work
编辑:我对来自TransactionManagementError 的消息感到困惑,因为如果在我的except 中我会这样做:
connection._cursor().connection.rollback()
而不是 django transaction.rollback(),MyModel.objects.all() 成功,如果我的代码“不在事务管理下”,这没有意义。不在事务管理下的代码(我认为这意味着它正在使用自动提交)可以具有跨越多个查询的事务也是没有意义的。
编辑#2:我知道使用手动事务控制能够从这些错误中恢复,但我不应该能够没有手动恢复交易控制?我的理解是,如果我使用自动提交,每个事务应该只有一次写入,所以它应该不影响以后的数据库活动。
编辑 #3: 这是几年后的事了,但在 django 1.4(不确定更高版本)中,这里的另一个问题是 Model.objects.bulk_create() 不尊重自动提交行为。 p>
版本:
- Django:1.4(
TransactionMiddleWare未启用) - Python:2.7
- Postgres:9.1
【问题讨论】:
-
您尝试过Savepoint rollback 的建议吗?文档不清楚,但您可能需要处于
transaction.commit_manually模式才能使transaction.rollback工作。查看模式here。 -
我认为可能是这种情况,但最好不必对项目中的每次保存都使用手动事务控制
-
保存点对我没有帮助,因为我使用的是默认的自动提交行为。
标签: python django postgresql transactions postgresql-9.1