Django-celery任务和django交易

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (153)

我对交易和芹菜任务有疑问。所以当然,如果你有一个交易和芹菜任务访问相同的表/记录我们将有竞争条件,这对我来说并不神秘。

但是,请考虑以下代码:

def f(self):
   # function of module that inherits from models.Model
   self.field_a = datetime.now()

   self.save()
   transaction.commit_unless_managed()

   # depending on the configuration of this module
   # this might return None or a datetime object.
   eta = self.get_task_eta()

   if eta:
       celery_task_do_something.apply_async(args=(self.pk, self.__class__),
                                            eta=eta)
   else:
       celery_task_do_something.delay(self.pk, self.__class__)

这是芹菜任务:

def celery_task_do_something(pk, cls):

    o = cls.objects.get(pk=pk)

    if o.field_a:
        # perform something
        return True
    return False

正如您所看到的,在创建我们调用的任务之前transaction.commit_unless_managed,它应该提交,因为当前没有管理django事务。

但是,在运行芹菜任务时,field_a未设置该字段。

我的问题

既然我们在创建任务之前就已经提交了,那么是否还存在竞争条件?

附加信息

  • 我们正在使用Postgres 9.1版
  • 每个事务都使用READ COMMITTED隔离级别运行
  • dowant.lib.db.backends.postgresql_psycopg2_debugger field_a已设置不同的带引擎的数据库上,任务按预期工作。使用引擎会dowant.lib.db.backends.postgresql_psycopg2_hstore_ready出现所描述的问题(不确定它是否与引擎有关)。
  • 芹菜版是2.2
  • 我试过不同的数据库。除了发动机改变之外,仍然是相同的行为。所以这就是我提到这一点的原因。

非常感谢。

提问于
用户回答回答于
用户回答回答于

尝试添加self.__class__.objects.select_for_update().get(pk=self.pk)之前save,看看会发生什么。

它应该阻止对该行的所有读取,直到提交完成。

扫码关注云+社区

领取腾讯云代金券