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, что означает, что синхронизация уже началась и приложение должно прервать/провалить попытку синхронизации.

Мои вопросы таковы

  1. Позволит ли такой подход избежать условий гонки и гарантировать отсутствие одновременной синхронизации?
  2. Есть ли лучший способ сделать это?

Я использую стандартный уровень изоляции Djangos, который равен READ_COMMITED. Я не хочу блокировать чтение во время синхронизации, так как затронутые таблицы часто читаются. Конечно, после успешной или неудачной синхронизации я буду устанавливать флаг is_syncing обратно в false.

Я пробовал этот подход, но трудно быть уверенным, что он работает во всех случаях.

Вернуться на верх