gpt4 book ai didi

python - 保存模型时确保原子性

转载 作者:太空狗 更新时间:2023-10-30 01:56:27 24 4
gpt4 key购买 nike

我是 Django 的新手,我不确定如何管理并发。

我正在构建一个预留设备的应用程序。我有一个带有 ManytomanyField 设备的预订模型。 当我创建新的预订时,我必须确保所有设备都可用。我的代码的第一个版本不关心并发性:

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() 将在开始时获取关键行的行级锁。但是假设您有另一个 View ,允许人们输入预订 pk 并更改开始和结束时间,或者添加新设备。这可能会导致不一致,除非您在与该 Reservation 关联的 Equipment 行上明确执行相同的 select_for_update()

请注意,您的检查效率不高。每当您在循环中执行查询时,您都应该寻找替代方案。在您的情况下,您应该能够找到与单个查询的冲突(JOINs 表):

has_conflict = Reservation.objects.filter(begin__lte=end,
end__gte=begin,
equipment__pk__in=keys).exists()

(当然,您仍然有并发问题,因此您仍然需要获取适当的锁或使用不同的事务隔离级别。)

我如何知道交易是否失败并通知用户?

事务不会失败,它只会阻塞直到锁被释放。如果您希望事务失败,您可以使用 select_for_update(nowait=True)(在某些数据库上)。

关于python - 保存模型时确保原子性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30330874/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com