如何在将模型字段更新到最新时间戳时避免竞争条件

时间:2017-05-25 20:49:36

标签: django postgresql django-orm race-condition

我需要跟踪帖子中提到用户的最近时间,并在每次根据帖子的发布时间创建新帖子时更新此字段。

我目前的代码如下:

from django.db.models.signals import post_save
from django.dispatch import receiver
from messageboard.models import Post

@receiver(post_save, sender=Post)
def user_last_mentioned_updater(sender, instance, **kwargs):
    for users in instance.mentions:
        user.last_mentioned = max(user.last_mentioned, instance.timestamp)
        user.save()

但是,如果同时处理两个帖子,则可能会将last_mentioned字段留在较早帖子的时间戳上。

不幸的是,F不支持max操作,当我尝试时,我得到TypeError: unorderable types: datetime.datetime() > F()

user.last_mentioned = max(F('last_mentioned'), instance.timestamp)

如何避免这种竞争状况?

如果重要的话,目前我正在使用Postgresql进行ORM,虽然这可能会有所变化。

1 个答案:

答案 0 :(得分:2)

这是一个应该没有竞争条件且效率更高的版本:

@receiver(post_save, sender=Post)
def user_last_mentioned_updater(sender, instance, **kwargs)
    User.objects.filter(
        id__in=[u.id for u in instance.mentions],
        last_mentioned__lt=instance.timestamp,
    ).update(last_mentioned=instance.timestamp)

也就是说,我们选择所提到的时间戳需要更新的用户,并在一个SQL语句中更新它们。