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() 的事务简短的主要内容,如果未能解决你的问题,请参考以下文章