Django芹菜任务和Django事务



我有一个关于事务和芹菜任务的问题。因此,对我来说,这并不神秘,当然,如果您有一个事务和一个芹菜任务访问同一个表/记录,我们将面临竞争条件。

但是,请考虑以下代码:

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

  • 我尝试了不同的数据库。仍然是相同的行为,除非发动机发生变化。所以这就是我提到这个的原因。

非常感谢。

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

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

这很晚了,但由于django 1.9

transaction.on_commit(lambda: enqueue_atask()))

相关内容

  • 没有找到相关文章

最新更新