当在transaction.atomic块中执行代码并引发异常时,数据库处理程序被标记为需要回滚。如果仍然在该transaction.atomic块中执行后续查询,则会引发以下错误:
TransactionManagementError:当前发生错误 交易。在“原子”
结束之前,您无法执行查询
此时,实际的根错误被模糊并且很难访问,因此您需要跳转到Django的事务代码。
一个可能导致此错误的简单示例:
def someview(request):
with transaction.atomic():
// do some things
instance = SomeModel.objects.create(...)
// some other db queries
@receiver(post_save, sender=SomeModel)
def non_critical_side_effect(
sender, instance, created, raw, using, update_fields, **kwargs
):
try:
// some query that causes a database error
SomeModelLog.objects.create(some_non_none_field=None)
except IntegrityError:
//notify ourselves, go on
pass
当你遇到这种情况时,你如何计算出真正发生的事情?你如何定期避免这种情况?
(下面的自我回答 - 但真正对其他人的想法感兴趣!)
答案 0 :(得分:2)
如果您正在使用django.db.transaction.atomic
上下文管理器并且被TransactionManagementError难倒,那么当exc_value
设置为{{1}时,您可以通过检查needs_rollback
的值来确定根本原因在True
中。这应该是导致需要回滚事务的异常。
首先避免这个错误,我采用了两种方法:
django.db.transaction.Atomic.__exit__
transaction.atomic
块,请确保此块中可能失败但不需要回滚整个事务的任何部分都包含在它们自己的子事务中。我的原始示例更正了,即使信号处理程序遇到数据库错误,视图仍可继续执行:
transaction.atomic