python – 保存模型时确保原子性
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – 保存模型时确保原子性,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含1841字,纯文字阅读大概需要3分钟。
内容图文
![python – 保存模型时确保原子性](/upload/InfoBanner/zyjiaocheng/787/69ffbc98c2f540979ea295ff01849f13.jpg)
我是Django的新手,我不知道如何管理并发.
我正在建立一个预备设备的应用程序.
我有一个带有ManytomanyField of Equipments的预订模型.
当我创建新预订时,我必须确保所有设备都可用.
我的代码的第一个版本不关心并发:
def validate_reservation(keys, begin, end):
eqpts = Equipment.objects.filter(pk__in=keys)
if all(eqpt.is_available(begin, end) for eqpt in eqpts):
res = Reservation(eqpts, begin, end)
res.save()
return True
else:
return False
is_available方法检查给定日期是否已有任何预留:
def is_available(self, begin, end):
return not self.reservations.filter(begin__lte=end, end__gte=begin).exists()
问题是运行此代码的两个用户可能会创建冲突预留,如果第一个在第二次检查设备可用性后保存他的预订.
我相信我可以通过交易来解决问题,所以我想出的是:
def validate_reservation(keys, begin, end):
with transaction.atomic():
eqpts = Equipment.objects.select_for_update().filter(pk__in=keys)
if all(eqpt.is_available(begin, end) for eqpt in eqpts):
res = Reservation(eqpts, begin, end)
res.save()
return True
else:
return False
这是否有预期的行为?
如何知道交易是否失败并通知用户?
有不同的更好的方式吗?
解决方法:
是的,只要您在修改可能影响可用性检查的任何内容之前始终使用select_for_update(),这应该可以正常工作.
此代码不会干扰自身,因为select_for_update()将在开头的关键行上获取行级锁.但是,假设您有另一种观点,允许人们输入预订pk并更改开始和结束时间,或添加新设备.这可能会导致不一致,除非您在与该预留关联的设备行上明确执行相同的select_for_update().
请注意,您的支票效率不高.无论何时你在循环中执行查询,你都应该寻找替代方案.在您的情况下,您应该能够找到与单个查询(加入表)的冲突:
has_conflict = Reservation.objects.filter(begin__lte=end,
end__gte=begin,
equipment__pk__in=keys).exists()
(当然,您仍然存在并发问题,因此您仍需要获取适当的锁或使用不同的事务隔离级别.)
如何知道交易是否失败并通知用户?
事务不会失败,它只会阻塞,直到锁被释放.如果您希望事务失败,可以使用select_for_update(nowait = True)(在某些数据库上).
内容总结
以上是互联网集市为您收集整理的python – 保存模型时确保原子性全部内容,希望文章能够帮你解决python – 保存模型时确保原子性所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。