你如何在Python/Django/MySQL中避免这种竞争条件?

Con*_*ion 3 python mysql database django race-condition

我有一个模型MyModel,它有一个字段expiration_datetime.

每次用户检索MyModel的实例时,我都需要先检查它是否已过期.如果它已经过期,我需要增加一些计数器,更新其他计数器,然后将expiration_datetime扩展到将来的某个时间.

所以视图会做类似的事情:

if object.expiration_datetime < datetime.datetime.now(): 
    object.counter = F('counter') + 1 
    object.expiration_datetime = F('expiration_datetime') + datetime.timedelta(days=1) 
    object.save() 
Run Code Online (Sandbox Code Playgroud)

上面的代码中存在竞争条件.假设线程1检查并发现当前实例已过期,它继续增加计数器并延长到期日期时间.但是在它可以这样做之前,线程2被安排并且做同样的事情.到线程1最终完成时,计数器已递增两次,expration_datetime已延长两次.

这看起来应该是一个非常常见的问题.处理它的最有效方法是什么?理想情况下,我希望能够以数据库可移植的方式在Django中处理它.

wup*_*tah 7

这可能是乐观锁定的一个很好的用例.有几种方法可以做到:

  • 您可以拥有版本号,并运行UPDATE查询以使其始终包含WHERE子句中的版本号,然后检查是否有任何行已更改.
  • WHERE子句中包括记录的每个值(在您所做的更改之前),这样您就可以确保保存的记录与您读取时的记录完全相同.

如何在Django中实现乐观锁定?看看这个问题:Django:我如何防止数据库条目的并发修改.