【问题标题】:How to avoid race condition in updating model field to newest timestamp如何在将模型字段更新为最新时间戳时避免竞争条件
【发布时间】:2023-03-17 22:04:01
【问题描述】:

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

我当前的代码如下所示:

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,尽管这可能会发生变化。

【问题讨论】:

    标签: django postgresql django-orm race-condition


    【解决方案1】:

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

    @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 语句中进行更新。

    【讨论】:

      猜你喜欢
      • 2019-10-23
      • 1970-01-01
      • 1970-01-01
      • 2021-04-01
      • 2019-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多