not*_*peg 6 python django postgresql transactions postgresql-9.1
IntegrityError或任何其他错误中恢复的正确方法,这些错误可能会导致我的交易失败而不使用手动事务控制?在我的应用程序中,我遇到了IntegrityError我想从中恢复的问题,这搞砸了以后的数据库活动,让我:
DatabaseError: current transaction is aborted, commands ignored until end of transaction block`
Run Code Online (Sandbox Code Playgroud)
对于忽略后的所有数据库活动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
Run Code Online (Sandbox Code Playgroud)
根据文档,从a恢复的解决方案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
Run Code Online (Sandbox Code Playgroud)
编辑:我对来自的消息感到困惑TransactionManagementError,因为如果我在我except做的话:
connection._cursor().connection.rollback()
Run Code Online (Sandbox Code Playgroud)
而不是django transaction.rollback(),MyModel.objects.all()成功,如果我的代码"不在交易管理之下",这是没有意义的.没有在事务管理下的代码(我假设它意味着它使用自动提交),也可能有跨越多个查询的事务也没有意义.
编辑#2:我知道使用手动事务控制能够从这些错误中恢复,但是如果没有手动事务控制,我不应该能够恢复吗?我的理解是,如果我使用自动提交,应该只有每个事务写的,所以应该不会影响以后的数据库活动.
编辑#3:这是几年后,但在django 1.4(不确定更高版本),这里的另一个问题是Model.objects.bulk_create()不尊重自动提交行为.
TransactionMiddleWare在未启用)Django的默认提交模式是AutoCommit。为了进行回滚,您需要将执行工作的代码包装在事务中。[文档]
with transaction.commit_on_success():
# Your code here. Errors will auto-rollback.
Run Code Online (Sandbox Code Playgroud)
要获得数据库级别自动提交,您将需要在数据库设置字典中使用以下选项。
'OPTIONS': {'autocommit': True,}
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用显式保存点来回滚。[文档]
@transaction.commit_manually
def viewfunc(request):
a.save()
# open transaction now contains a.save()
sid = transaction.savepoint()
b.save()
# open transaction now contains a.save() and b.save()
if want_to_keep_b:
transaction.savepoint_commit(sid)
# open transaction still contains a.save() and b.save()
else:
transaction.savepoint_rollback(sid)
# open transaction now contains only a.save()
transaction.commit()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2117 次 |
| 最近记录: |