django get_or_create()不是线程安全的

最近数据库出现了莫名的BUG,一条记录会同时创建两次。

为了解决这个问题,首先看了一下代码,代码用了get_or_create()这个方法,翻看了源码:

    def get_or_create(self, defaults=None, **kwargs):
        """
        Look up an object with the given kwargs, creating one if necessary.
        Return a tuple of (object, created), where created is a boolean
        specifying whether an object was created.
        """
        lookup, params = self._extract_model_params(defaults, **kwargs)
        # The get() needs to be targeted at the write database in order
        # to avoid potential transaction consistency problems.
        self._for_write = True
        try:
            return self.get(**lookup), False
        except self.model.DoesNotExist:
            return self._create_object_from_params(lookup, params)

原来这个方法不是原子的,如果并发操作会出现问题(就像我的创建了两次)。不过这个方法的名字太“原子”了,会让人误以为是线程安全的,如果改成get_or_create_unsafely()可能会让人谨慎起来。

接着,我查看了一下日志,果真是有并发的请求,难怪会出现这样的问题。

解决方案:

  1. 配合事务一起使用
  2. 在model层加限制uniqueunique_together

大家如果喜欢,欢迎点赞分享评论哦!

你可能感兴趣的:(django get_or_create()不是线程安全的)