【问题标题】:TransactionManagementError obscuring root exceptionTransactionManagementError 掩盖根异常
【发布时间】:2017-08-25 23:37:04
【问题描述】:

当代码在 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

当您遇到这种情况时,您如何弄清楚实际发生了什么,以及您通常如何避免这种情况?

(下面的自我回答 - 但真正对他人的想法感兴趣!)

【问题讨论】:

    标签: django


    【解决方案1】:

    如果您正在使用django.db.transaction.atomic 上下文管理器并且被 TransactionManagementError 难住了,您可以通过在needs_rollback 中将needs_rollback 设置为True 时检查exc_value 的值来确定根本原因。这应该是提示需要回滚事务的异常。

    首先为了避免这个错误,我采用了两种方法:

    • 避免在transaction.atomic 中包装大块代码
    • 如果您确实需要更大的 transaction.atomic 块,请确保该块中任何可能失败而无需回滚整个事务的部分都包装在它们自己的子事务中。

    我的原始示例已更正,即使出现信号处理程序遇到数据库错误,视图仍可以继续执行:

    def someview(request):
        with transaction.atomic():
           // do some things
           SomeModel.objects.create(invalid_field=123)
    
    @receiver(post_save, sender=SomeModel)
    def non_critical_side_effect(
        sender, instance, created, raw, using, update_fields, **kwargs
    ):
        try:
            with transaction.atomic():
                // some query that causes a database error
        except IntegrityError:
            // notify ourselves, go on
            pass
    

    【讨论】:

    • 如何访问django.db.transaction.Atomic.__exit__?您是否对上下文管理器进行了子类化?
    • @Antimony 我可能只是在调试时使用了pdbbreakpoint
    • 我试过了,但完全没用 'An error occurred in the current transaction. You can\'t execute queries until the end of the \'atomic\' block.' :( 仍然不知道如何调试这个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 2014-07-05
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多