Django 1.6建议@transaction.atomic
作为1.5中交易管理改革的一部分。
我有一个由Django管理命令调用的函数,该命令又由cron调用,即在这种情况下没有HTTP请求触发事务。片段:
from django.db import transaction
@transaction.commit_on_success
def my_function():
# code here
在上面的代码块中,commit_on_success
使用单个事务处理my_function
中完成的所有工作。
用@transaction.commit_on_success
替换@transaction.atomic
会导致相同的行为吗? @transaction.atomic
docs state:
Atomicity是数据库事务的定义属性。原子 允许我们创建一个代码块,其中包含原子性 数据库有保证。如果代码块成功 完成后,更改将提交到数据库。如果有的话 异常,更改将被回滚。
我认为它们会导致相同的行为;正确的吗?
答案 0 :(得分:59)
根据我在这个主题上阅读的文档,这些装饰器嵌套时会有很大的不同。
嵌套两个atomic
块与嵌套两个commit_on_success
块的效果不同。
问题在于您希望从这些块中获得两种保证。
嵌套块时无法提供两种保证。如果在离开最里面的块之后但在离开最外面的块之前引发异常,则必须以两种方式之一失败:
这是您找到差异的地方。使用commit_on_success
将为最里面的块提供持久性,但是对于最外面的块没有原子性。使用atomic
将为最外面的块提供原子性,但对最里面的块没有持久性。
在嵌套的情况下简单地引发异常可能会阻止您遇到问题。最里面的块总是引发异常,因此它永远不会承诺任何持久性。但这会失去一些灵活性。
更好的解决方案是更准确地了解您的要求。如果您可以单独询问原子性和耐久性,那么您可以执行嵌套。您只需确保请求持久性的每个块都超出请求原子性的块。在请求原子性的块内请求持久性将不得不引发异常。
atomic
应该提供原子性部分。据我所知,django 1.6.1没有装饰器,可以要求耐久性。我试着在codereview上写一个,posted。
答案 1 :(得分:44)
是。您应该在以前使用atomic
的地方使用commit_on_success
。
由于新的交易系统旨在更加健壮和一致,因此您可能会看到不同的行为。例如,如果您捕获数据库错误并尝试继续,您将看到TransactionManagementError
,而之前的行为未定义且可能与案例有关。
但是,如果你正确地做事,一切都应该继续以同样的方式运作。