该应用程序具有这些相关模型,公司,节点和日志。
class VCompany(models.Model):
company_name = models.CharField(max_length=50, ...)
class VNode(models.Model):
company = models.ForeignKey(VCompany, ...)
name1 = models.CharField(...)
name2 = models.CharField(...)
class Log(models.Model):
node = models.ForeignKey(VNode, ... )
VNode必须是唯一的。不幸的是,没有简单的独特/独特在一起。如果name1已知,则company和name1的组合是唯一的。如果name2已知,则company和name2的组合是唯一的。 name1或name2或两者都是已知的。
问题1:是否可以为上述案例构建一个独特的条款?怎么样?
芹菜任务用于通过处理文件中的某些数据在日志中创建记录。有许多芹菜任务同时运行以创建日志记录。创建日志记录时,可能需要创建vnode。这会导致创建重复的vnode记录。为了解决这个问题,我正在这样做:
with transaction.atomic():
# Get the company for update as a sync method.
company = VCompany.objects.select_for_update().get(company_name=company)
if name1:
node, create = VNode.objects.get_or_create(company=company, name1=... )
... set other node data ...
node.save()
return node
if name2:
node, create = VNode.objects.get_or_create(company=company, name2=... )
... set other node data ...
node.save()
return node
此代码显然有效。但是,如果我删除with transaction.atomic(),它会可靠地失败。
问题2:为什么需要transaction.atomic()?需要吗?
问题3:django的ORM什么时候发布select_for_update? get_or_create是否会在创建新节点之前释放它以便发生竞争条件?
感谢您提供任何线索!
答案 0 :(得分:1)
问题1:我不知道
问题2:
需要transaction_atomic,因为select_for_update仅在当前事务的持续时间内持有锁。否则,(如果您没有进行任何其他交易),它将立即释放锁定。
问题3:
当前事务关闭(提交或回滚)时释放锁。
get_or_create不是原子的,只有在db具有正确的唯一性约束时才是线程安全的。如果get_or_create违反唯一性约束,则会引发IntegrityError。
在您的情况下,锁定VCompany应该使VNode上的get_or_create方法无法失败。但是,只有在尝试创建VNode对象的任何位置正确锁定时才会出现这种情况。