【发布时间】:2018-04-14 02:10:51
【问题描述】:
我有一个 Django 1.11 + MySQL + Celery 4.1 项目,其中一个视图创建一个新的用户记录,然后启动一个 Celery 任务以执行与其相关的其他长时间运行的操作。
这种情况下的典型问题是确保在 Celery 任务执行之前将用户创建提交到数据库。否则,会出现竞争条件,如果在事务提交之前执行,任务可能会尝试访问不会退出的记录。
我学会解决此问题的方法是始终将记录创建包装在手动事务或原子块中,然后触发 Celery 任务。例如
def create_user():
with transaction.atomic():
user = User.objects.create(username='blah')
mytask.apply_async(args=[user.id])
@task
def mytask(user_id):
user = User.objects.get(id=user_id)
do_stuff(user)
但是,我仍然偶尔会在我的 Celery 工作日志中看到错误 DoesNotExist: User matching query does not exist,这意味着我的任务有时会在用户记录被提交之前执行。
这不是正确的策略还是我没有正确实施?
【问题讨论】:
-
看起来您需要在您的事务中使用
on_commit挂钩:docs.djangoproject.com/en/1.11/topics/db/transactions/…