Django использует update() на колонке bool в качестве блокировки операций приложения
В моем Django-приложении есть операция (синхронизация данных из внешней системы), которую я хочу ограничить от одновременного выполнения дважды. Для контекста, синхронизация данных может происходить из-за периодически запланированного задания или из-за того, что пользователь вручную/явно запрашивает синхронизацию. Если два задания синхронизации происходят одновременно, база данных может иметь нежелательное состояние (и даже вызвать нежелательные эффекты в приложении в результате). В случае, если несколько попыток синхронизации происходят одновременно, я хотел бы, чтобы одна из них была успешной, а остальные - неудачными. Решение, которое я придумал, заключается в том, чтобы иметь булеву колонку с именем is_syncing
в моей модели Tenant
, поскольку данные и логика синхронизации относятся к конкретному арендатору. Идея заключается в том, что перед попыткой обновления я должен вызвать
Tenant.objects.filter(id=tenant_id, is_syncing=False).update(is_syncing=True)
который вернет количество затронутых строк.
Он должен вернуть 1
, если is_syncing
был ранее False
, что означает, что операция синхронизации может произойти. Или же он может вернуть 0
, что означает, что синхронизация уже началась и приложение должно прервать/провалить попытку синхронизации.
Мои вопросы таковы
- Позволит ли такой подход избежать условий гонки и гарантировать отсутствие одновременной синхронизации?
- Есть ли лучший способ сделать это?
Я использую стандартный уровень изоляции Djangos, который равен READ_COMMITED
. Я не хочу блокировать чтение во время синхронизации, так как затронутые таблицы часто читаются. Конечно, после успешной или неудачной синхронизации я буду устанавливать флаг is_syncing
обратно в false.
Я пробовал этот подход, но трудно быть уверенным, что он работает во всех случаях.