我遇到了一个有竞争条件的问题,我对如何解决它并不满意。寻找更惯用的方法。
# Celery task
@task
@transaction.atomic
def send_messages_task()
unsent_messages = Message.objects.select_for_update().exclude(sent=True)
# Critical section
if unsent_messages.exists():
group(send_message_task.s(m.id) for m in unsent_messages).apply_async()
# unsent_messages executes new query, table is not locked
# any newly created messages will be marked sent but never sent.
unsent_messages.update(sent=True)
我通过在list
声明中调用select_for_update
来解决它。令我感到惊讶的是,事务和select_for_update
调用不会提供表锁以防止此操作或至少冻结查询。什么是更好的方法。