当外部事务失败时,嵌套的transaction.atomic()上下文管理器避免回滚

时间:2015-08-18 11:40:39

标签: python django python-2.7 transactions django-orm

我遵循以下情况:

@transaction.atomic()
def some_method():
    # some database logic
    a.save()  # Success. Eligible for Rollback.

    with transaction.atomic():
        # some more database logic
        # Success. Shouldn't be rollbacked
        b.save()

    raise Exception

我想要做的是,当我提出Exception时,内部事务集块的更改不应该回滚,但是在外部块中完成的更改应该是。

这意味着,回滚 - a.save(),但提交b.save()。那可能吗?我想那里的上下文管理器会创建一个保存点。那么,如果内部块成功运行,那么它是否应该提交直到保存点?它在这种情况下的确切表现如何?

我读了docs here,其中说:

  

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

它说,它可以回滚,但不会回滚。究竟是什么意思?回滚确定吗?

1 个答案:

答案 0 :(得分:1)

首先,如果@transaction.atomic添加到some_method,如果内部任何地方发生Exception,则会回滚所有内容。

现在,如果您移除装饰器并在原子块内引发Exception,您或多或少得到您想要的东西:b将被提交,而不是。

def some_method(request):
    b.save()

    with transaction.atomic():
        a.save()
        raise Exception('')

在这种情况下,如果你在块之外引发Exception,那么一切(在Exception之前)将被提交(在事务中没有引发Exception

我认为文档摘录涉及以下情况:

def funA():
    with transaction.atomic():
        funB()
        #code A

def funB():
    with transaction.atomic():
        #code B

如果代码A 中出现Exception代码B 中的所有内容都将被回滚。