sql - Django 嵌套事务 - “with transaction.atomic()” -- 寻求澄清

标签 sql django transactions

Django nested transactions - “with transaction.atomic()”问题是,鉴于这个......

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

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

functionB失败并回滚,是否 functionA也回滚?

凯文克里斯托弗亨利回答说:“是的,如果在任何一个函数中发生异常,它们都会被回滚。”然后他引用 the docs , 哪一个州:

atomic blocks can be nested. In this case, when an inner block completes successfully, its effects can still be rolled back if an exception is raised in the outer block at a later point.



此文档引用似乎没有解决原始问题。该文档说,当 INNER BLOCK(即 functionB)成功完成时,如果 OUTER 块(即 functionA)引发异常,其效果仍然可以回滚。但问题指的是相反的情况。问题是,如果 INNER 块( functionB )失败,OUTER 块( functionA )是否回滚?这个文档引用没有解决这种情况。

然而,在文档的更深处,我们看到了这个例子......
from django.db import IntegrityError, transaction

@transaction.atomic
def viewfunc(request):
    create_parent()

    try:
        with transaction.atomic():
            generate_relationships()
    except IntegrityError:
        handle_exception()

    add_children()

……接着是这个评论……

In this example, even if generate_relationships() causes a database error by breaking an integrity constraint, you can execute queries in add_children(), and the changes from create_parent() are still there.



如果我正确地阅读了文档,那就是在说调用 generate_relationships() (这类似于原始问题中对 functionB 的调用)可以失败以及在 create_parent() 中所做的更改和 add_children()将提交给数据库。这似乎与凯文克里斯托弗亨利的回答相矛盾。

让我感到困惑的是,我在 Django nested Transaction.atomic 中看到了相同的问题/答案。 .

我是 Django 和 stackoverflow 的新手,所以我对阅读文档没有太大信心,但这似乎与这两个响应相矛盾。我正在寻找更有经验的人的一些说明。非常感谢。

最佳答案

这是一些带有嵌套事务块和数据库操作的伪代码 X , Y , 和 Z :

with transaction.atomic():
    X
    with transaction.atomic():
        Y
    Z

X引发异常,那么显然没有任何操作将有机会首先提交。

Y引发异常 - 这是您引用的问题 - 然后外部块也将回滚。这与嵌套事务本身没有任何关系,它的发生是因为 Python 异常冒泡了。外部块将因异常退出,这总是会导致回滚。无论最初是什么导致异常,都是如此。

不明显的情况是当 Z 时会发生什么引发异常,这就是文档特别注意的原因。如 referenced , 两者 XY将被回滚:

When an inner block completes successfully, its effects can still be rolled back if an exception is raised in the outer block at a later point.



现在,还可以捕获嵌套操作引发的异常。
with transaction.atomic():
    X
    try:
        with transaction.atomic():
            Y
    except IntgrityError:
        pass
    Z

在这种情况下,如果 Y抛出异常,内部块将被回滚(因为它以异常退出)但外部块不会(因为它没有)。

这与您提到的两个答案中的任何一个中的信息都不矛盾,因为那些解决了不涉及捕获任何异常的特定问题(带有代码示例)。

无论如何,感谢您的反馈和提供更全面答案的机会。

关于sql - Django 嵌套事务 - “with transaction.atomic()” -- 寻求澄清,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48835309/

相关文章:

django - Supervisord 抛出错误 : "couldn' t exec/var/application/gunicorn_start: ENOEXEC"

sql-server - 分布式事务的性能开销

javascript - Nodejs 是否将单个函数中的单独数据库操作设为原子操作?

c# - 如何针对不同的上下文使用事务?

c# - 如何在 MVC 中使用 Windows 身份验证,但使用较新的身份数据库表进行角色存储?

php - 警告 : implode() [function. 内爆]:表单复选框中传递的参数无效

javascript - Django:日期格式管理和 unique_together -> "20/03/2020"值具有无效的日期格式。它必须采用 YYYY-MM-DD 格式。”]

mysql - 使用 Navicat 在 2 列上创建一个键

用于大规模分析的 Python 策略(即时或延迟)

python - Sentry.io 动态忽略记录器