django get_or_create()不是线程安全的

作者: jarhmj | 来源:发表于2019-01-29 11:35 被阅读1次

    最近数据库出现了莫名的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()不是线程安全的

        本文链接:https://www.haomeiwen.com/subject/teztsqtx.html