[英]Django Record Locking and Atomic Transactions
我正在尝试在我正在做的项目中实施一些关键更新。 总之,我需要从一个工作文件中获取信息,该文件进行一些进一步的处理,然后将其更新为最终文件。 此信息来自不同的来源,因此最好在中间文件上执行,然后将其写入最终文件。
我的问题是一些细节线数据在途中丢失了。 我在下面的文件中复制了这个问题以消除任何杂物。 只需在 manage.py shell 中运行函数即可。 这显示在 Mariadb 和 Postgresql 中。
有没有更好的方法来实现这一点而不是解决方法?
模型.py:
import random
from decimal import Decimal
from django.db import models, transaction
class Head(models.Model):
name = models.CharField(max_length=20, default="")
h1_text = models.CharField(max_length=20, default="")
def update(self):
tmp1 = Tmp1Head()
tmp1.name = self.h1_text
tmp1.save()
for line in self.head_lines.all():
tl1 = Tmp1Line()
tl1.head = tmp1
tl1.data_text = line.data_text
tl1.t1_data = line.t1_data
tl1.t2_data = Decimal(random.random())
tl1.save()
with transaction.atomic():
transaction.on_commit(tmp1.update)
tmp1.delete() # All fine - remove this work transaction.
return True
class Line(models.Model):
head = models.ForeignKey(Head, on_delete=models.CASCADE, related_name='head_lines')
data_text = models.CharField(max_length=20, default="")
t1_data = models.DecimalField(max_digits=12, decimal_places=2)
class Tmp1Head(models.Model):
name = models.CharField(max_length=20, default="")
def update(self):
tmp2 = Tmp2Head()
tmp2.name = self.name
tmp2.save()
for line in self.tmp1_lines.all():
tl2 = Tmp2Line()
tl2.head = tmp2
tl2.data_summary = line.data_text
tl2.final_data = line.t1_data * line.t2_data
tl2.save()
class Tmp1Line(models.Model):
head = models.ForeignKey(Tmp1Head, on_delete=models.CASCADE, related_name='tmp1_lines')
data_text = models.CharField(max_length=20, default="")
t1_data = models.DecimalField(max_digits=12, decimal_places=2)
t2_data = models.DecimalField(max_digits=12, decimal_places=2)
class Tmp2Head(models.Model):
name = models.CharField(max_length=20, default="")
class Tmp2Line(models.Model):
head = models.ForeignKey(Tmp2Head, on_delete=models.CASCADE, related_name='tmp2_lines')
data_summary = models.CharField(max_length=20, default="")
final_data = models.DecimalField(max_digits=12, decimal_places=2)
视图.py
from .models import *
def populate():
Head.objects.all().delete()
Tmp1Head.objects.all().delete()
Tmp2Head.objects.all().delete()
head = Head.objects.create(name="test", h1_text="test text")
for tmp in range(1, 5):
Line.objects.create(head=head,
data_text=f"data line:{tmp}",
t1_data=tmp)
def test1(): # all fine but no locking.
batch = Head.objects.first()
batch.update()
def test2(): # record locking but the data lines get lost in the final table.
with transaction.atomic():
batch = Head.objects.select_for_update().first()
batch.update()
def test3(): # record locking, no data lost, but the temp data is not removed.
"""
Same as test 2 but remove the below line from update function in the Head model.
tmp1.delete() # All fine - remove this work transaction.
"""
with transaction.atomic():
batch = Head.objects.select_for_update().first()
batch.update()
为了解决这个问题,我拿走了保存点,现在一切似乎都很好。 它应该是安全的,因为只有程序才能访问临时文件。
我从models.py中删除了这个:
# with transaction.atomic():
# transaction.on_commit(tmp1.update)
tmp1.update()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.