Django嵌套事务-“ with transaction.atomic()”-寻求澄清 [英] Django nested transactions - “with transaction.atomic()” -- Seeking Clarification

查看:136
本文介绍了Django嵌套事务-“ with transaction.atomic()”-寻求澄清的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Django嵌套事务中- with transaction.atomic() 问题是,鉴于此...

In Django nested transactions - "with transaction.atomic()" the question is, given this...

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

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

如果 functionB 失败并回滚,则 functionA 也会回滚吗?

If functionB fails and rolls back, does functionA roll back too?

Kevin Christopher Henry回答说:是的,如果两个函数中都发生异常,它们都会被回滚。然后,他引用文档,哪个状态:

Kevin Christopher Henry replies with, "Yes, if an exception happens in either function they will both be rolled back." He then quotes the docs, which state:


原子块可以嵌套。在这种情况下,当一个内部块成功完成时,如果稍后在外部块中引发异常,它的效果仍然可以回滚。

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.

此文档引用似乎并未解决原始问题。医生说,当内部块( functionB )成功完成时,如果外部块(即functionA)引发异常,则其效果仍然可以回滚。但是问题是相反的情况。问题问,如果INNER块( functionB )失败,OUTER块( functionA )是否回滚?此文档引用无法解决这种情况。

This documentation quote doesn't seem to address the original question. The doc is saying that when the INNER BLOCK (which is functionB) completes successfully, its effects can still be rolled back if the OUTER block (which is functionA) raises an exception. But the question refers to the opposite scenario. The question asks, if the INNER block (functionB) FAILS, is the OUTER block (functionA) rolled back? This doc quote doesn't address that scenario.

但是,在文档的更下方,我们看到了此示例...

However, further down in the doc we see this example...

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()

...之后是此评论...

...followed by this commentary...


在此示例中,即使 generate_relationships()通过破坏完整性约束导致数据库错误,也可以执行查询在 add_children()中,并且从 create_parent()所做的更改仍然存在。

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()的调用(类似于呼叫<$ c原始问题中的$ c> functionB 可以失败,并且 create_parent() add_children()将被提交到数据库。这似乎与凯文·克里斯托弗·亨利的答案相矛盾。

If I'm reading the doc correctly it's saying the call to generate_relationships() (which is analogous to the call to functionB in the original question) can FAIL and the changes made in create_parent() and add_children() will be committed to the database. This seems to contradict Kevin Christopher Henry's answer.

令我困惑的是,我在 Django嵌套的Transaction.atomic

我是Django和stackoverflow的新手,所以我对文档的阅读并没有很大的信心,但这似乎与这两个答案都相矛盾。我正在寻找经验更丰富的人做些澄清。

I'm new to both Django and stackoverflow, so I don't have a lot of confidence in my reading of the doc, but it seems to contradict both of these responses. I'm looking for some clarification from someone more experienced. Thanks you so much.

推荐答案

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

Here is some pseudo-code with nested transaction blocks and database operations X, Y, and Z:

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

如果 X 引发异常,那么显然任何操作都不会

If X raises an exception then obviously none of the operations will get the chance to commit in the first place.

如果 Y 引发异常,这就是您所引用的问题—然后,外部块也会回滚。实质上,这与嵌套事务无关,这是因为Python异常冒出来了。外部块将被异常退出,该异常总是导致回滚。

If Y raises an exception—which was the question you referenced—then the outer block will also roll back. That doesn't have anything to do with nested transactions, per se, it happens because the Python exception bubbles up. The outer block will be exited by an exception, which always causes a rollback. That's true regardless of what caused the exception in the first place.

不明显的情况是 Z 引发了一个异常,这就是为什么文档将其特别引起注意。作为引用,两者 X Y 将回滚:

The non-obvious case is what happens when Z raises an exception, and that's why the documentation calls it out for special attention. As referenced, both X and Y will be rolled back:


内部块成功完成后,如果稍后在外部块中引发异常,其效果仍然可以回滚。

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.

现在,还可以捕获嵌套操作引发的异常。

Now, it's also possible to catch the exception raised by the nested operation.

with transaction.atomic():
    X
    try:
        with transaction.atomic():
            Y
    except IntgrityError:
        pass
    Z

在这种情况下,如果 Y 引发异常,则内部块将会回滚(因为它退出并带有异常),但外部块不会(因为它不会)。

In this case, if Y throws an exception the inner block will be rolled back (because it exits with an exception) but the outer block won't (because it doesn't).

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

That doesn't contradict the information in either of the two answers you mentioned since those addressed specific questions (with code examples) that didn't involve catching any exceptions.

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

In any case, thanks for the feedback and the chance to give a more comprehensive answer.

这篇关于Django嵌套事务-“ with transaction.atomic()”-寻求澄清的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆