Django - 保持基于 save() 的事务简短

Posted

技术标签:

【中文标题】Django - 保持基于 save() 的事务简短【英文标题】:Django - Keeping save() based transactions short 【发布时间】:2011-03-14 01:12:36 【问题描述】:

由于 django 模型 save() 方法 are not lazy,并且保持事务简短是一种普遍的好习惯,是否应该最好将保存推迟到事务块的末尾?

例如,代码示例 B 是否会比下面的代码示例 A 保持交易打开的时间更短?

代码示例 A:

from django.db import transaction
from my_app.models import MyModel

@transaction.commit_on_success
def model_altering_method():
    for inst in MyModel.objects.all()[0:5000]:
        inst.name = 'Joel Spolsky'
        # Some models independent time consuming operations...
        inst.save()

代码示例 B:

from django.db import transaction
from my_app.models import MyModel

@transaction.commit_on_success
def model_altering_method():
    instances_to_save = []
    for inst in MyModel.objects.all()[0:5000]:
        inst.name = 'Joel Spolsky'
        # Some models independent time consuming operations...
        instances_to_save.append(inst)

    for inst in instances_to_save:
        inst.save()

【问题讨论】:

【参考方案1】:

我不确定,但这是我的理论 - 我认为您的 commit_manually 装饰器将开始一个新事务,而不是在您进行第一次保存时立即生成一个新事务。所以我的理论是代码示例 B 会使事务保持更长时间,因为它必须循环遍历模型列表两次。

同样,这只是一个理论 - 它还可能取决于您使用的 DBMS 以及实际事务何时开始(另一种理论)。

【讨论】:

在许多情况下,为事务准备数据需要很长时间。如果如您所说,一旦装饰块开始就打开事务,那么就有将准备块和事务块分开的动机......如果是这种情况,那么它应该记录在事务部分下的 django 文档中.【参考方案2】:

Django 的默认行为是使用打开的事务运行,当调用任何内置的数据更改模型函数时,它会自动提交该事务。在 commit_on_success 或 commit_manually 装饰器的情况下,django 不会在 save() 时提交,而是在函数执行成功完成或 transaction.commit() 命令时提交。

因此,如果可能的话,优雅的方法是将事务处理代码和其他耗时的代码分开:

from django.db import transaction
from my_app.models import MyModel

@transaction.commit_on_success
def do_transaction(instances_to_save):
    for inst in instances_to_save:
        inst.save()

def model_altering_method():
    instances_to_save = []
    for inst in MyModel.objects.all()[0:5000]:
        inst.name = 'Joel Spolsky'
        # Some models independent time consuming operations...
        instances_to_save.append(inst)
    do_transaction(instances_to_save)

如果这是不可能的设计明智的,例如您需要 instance.id 信息,对于新实例,您只能在第一次 save() 后获得,尝试将您的流程分解为合理大小的工作单元,以免事务长时间保持打开状态。

还要注意,长时间的交易并不总是一件坏事。如果您的应用程序是唯一修改数据库的实体,它实际上可能没问题。但是,您应该检查数据库的特定配置以查看事务(或空闲事务)的时间限制。

【讨论】:

以上是关于Django - 保持基于 save() 的事务简短的主要内容,如果未能解决你的问题,请参考以下文章

django事务中发信号怎么保证post save执行时数据已经写入数据库

Django 数据库事务

Django 数据库事务

MySQL事务并发带来的问题以及其解决方案分析

django 保存订单乐观锁的使用

数据库事务Redis缓存