Django 嵌套事务 - “with transaction.atomic()”

Posted

技术标签:

【中文标题】Django 嵌套事务 - “with transaction.atomic()”【英文标题】:Django nested transactions - “with transaction.atomic()” 【发布时间】:2014-03-27 13:12:50 【问题描述】:

我想知道我是否有这样的事情:

def functionA():
    with transaction.atomic():
        #save something
        functionB()

def functionB():
    with transaction.atomic():
        #save another thing

有人知道会发生什么吗?如果functionB失败了,functionA也会回滚吗?

谢谢!

【问题讨论】:

记住,你也可以使用@transaction.atomic 装饰器。 【参考方案1】:
with transaction.atomic(): # Outer atomic, start a new 
          
     transaction.on_commit(foo)
     try:
       with transaction.atomic(): # Inner atomic block, create a savepoint
           transaction.on_commit(bar)
           raise SomeError() # Raising an exception - abort the savepoint
     except SomeError:
pass
# foo() will be called, but not bar()

【讨论】:

【参考方案2】:

是的,它会的。不管嵌套如何,如果一个原子块被异常it will roll back退出:

如果代码块成功完成,则将更改提交到数据库。如果出现异常,则回滚更改。

还要注意,外部块中的异常会导致内部块回滚,并且可以捕获内部块中的异常以防止外部块回滚。文档解决了这些问题。 (或查看here 了解有关嵌套事务的更全面的后续问题)。

【讨论】:

“可以捕获内部块中的异常以防止外部块回滚”这部分似乎与“避免在原子内部捕获异常!”的做法相冲突。 docs.djangoproject.com/en/3.0/topics/db/transactions/… @JialinZou:没有冲突。如果您阅读文档中的该部分,您将看到对捕获数据库错误的“正确方法”的引用,其示例涉及在内部块中捕获异常。他们试图警告您注意的是捕获异常并尝试在中断状态下继续进行事务。正确的做法是将内部代码用atomic()包裹起来,以确保在继续之前回滚损坏的数据库操作。 感谢您的澄清!这很有帮助。

以上是关于Django 嵌套事务 - “with transaction.atomic()”的主要内容,如果未能解决你的问题,请参考以下文章

laravel 嵌套事务

Spring嵌套事务原理

面试突击:加入事务和嵌套事务有什么区别?

sqlserver事务可以嵌套多少事务,为啥,回答对的还可以加分

Laravel 嵌套事务 transactions

MySQL中是不是允许嵌套事务?