在Django嵌套事务--“with transaction.atomic()”,问题是,考虑到这一点.
def functionA():
with transaction.atomic():
#save something
functionB()
def functionB():
with transaction.atomic():
#save another thing如果functionB失败并回滚,functionA也会回滚吗?
回答道:“是的,如果在任何一个函数中出现异常,它们都会被回滚。”然后,他引用医生们的话说:
原子块可以嵌套。在这种情况下,当内部块成功完成时,如果稍后在外部块中引发异常,则仍然可以回滚其效果。
这个文档引用似乎没有解决原来的问题。文档是说,当内部块(即functionB)成功完成时,如果外部块(即functionA)引发异常,它的效果仍然可以回滚。但问题是相反的情况。问题是,如果内部块(functionB)失败,外部块(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()...followed通过这篇评论..。
在本例中,即使
generate_relationships()通过打破完整性约束导致数据库错误,您也可以在add_children()中执行查询,而来自create_parent()的更改仍然存在。
如果我正确地阅读了文档,这意味着对generate_relationships()的调用(类似于原始问题中对functionB的调用)可能失败,create_parent()和add_children()中所做的更改将提交到数据库中。这似乎与凯文·克里斯托弗·亨利的回答相矛盾。
令我费解的是,我在Django嵌套Transaction.atomic中看到了同样的问题/答案。
我对Django和stackoverflow都很陌生,所以我对我对文档的阅读没有很大的信心,但这似乎与这两种反应相矛盾。我在找一个更有经验的人澄清。非常感谢你。
发布于 2018-02-17 00:00:34
下面是一些带有嵌套事务块和数据库操作( X、Y和Z )的伪代码
with transaction.atomic():
X
with transaction.atomic():
Y
Z如果X引发异常,那么很明显,任何操作都不会首先获得提交的机会。
如果Y引发异常--这是您所引用的问题--那么外部块也会回滚。这与嵌套事务本身没有任何关系,发生这种情况是因为Python异常出现了气泡。外部块将被异常退出,这通常会导致回滚。不管是什么导致了异常,这都是正确的。
不明显的情况是,当Z引发异常时会发生什么,这就是为什么文档需要特别注意的原因。作为参考,X和Y都将被回滚:
当内部块成功完成时,如果稍后在外部块中引发异常,则仍然可以回滚其效果。
现在,还可以捕获嵌套操作引发的异常。
with transaction.atomic():
X
try:
with transaction.atomic():
Y
except IntgrityError:
pass
Z在本例中,如果Y抛出异常,内部块将被回滚(因为它与异常一起退出),但外部块不会(因为它没有)。
这与您提到的两种答案中的任何一种都不矛盾,因为它们解决了不涉及捕获任何异常的特定问题(包括代码示例)。
无论如何,谢谢你的反馈和给出一个更全面的答案的机会。
发布于 2018-02-16 22:18:36
第二个例子是捕获IntegrityError,因此外部事务原子不会注意到下面发生的错误
在try/try块中包装原子允许自然地处理完整性错误
这基本上是说,如果您希望下面的块不引发外部事务回滚,只需尝试/捕获完整性错误。
正如您在文档中已经指出的那样
原子块可以嵌套。在这种情况下,当内部块成功完成时,如果在外部块稍后在点引发异常,则仍然可以回滚它的效果。
因此,在默认情况下,回滚将随着错误的传播而发生,第二个示例是使外部事务回滚保持沉默的一种方法。
https://stackoverflow.com/questions/48835309
复制相似问题