Открыть сервисСервис

Оптимистичные блокировки

Оптимистичные блокировки (англ. optimistic locking) — это механизм управления конкурентным доступом к данным в информационных системах, при котором блокировка ресурса не накладывается на время выполнения транзакции, а проверка на конфликты выполняется непосредственно перед фиксацией изменений. Данный подход предполагает, что конфликты между параллельными транзакциями возникают редко (отсюда название «оптимистичный»), и поэтому накладные расходы на предварительную блокировку считаются избыточными. В случае обнаружения конфликта (например, изменения данных другой транзакцией) текущая транзакция откатывается и повторяется.

Принцип работы

Оптимистичные блокировки основаны на предположении, что большинство операций чтения и записи не пересекаются. Вместо того чтобы запрещать другим транзакциям доступ к данным на время выполнения, система позволяет всем транзакциям работать параллельно, но перед записью проверяет, не изменились ли данные с момента их чтения.

Процесс выполнения транзакции с оптимистичной блокировкой включает три этапа:

  1. Чтение (фаза чтения). Транзакция считывает данные и запоминает их текущее состояние (обычно в виде версии, временной метки или контрольной суммы). Никаких блокировок на этом этапе не накладывается.
  2. Вычисление (фаза проверки). Транзакция выполняет необходимые вычисления и готовит изменения. Перед записью она повторно считывает исходные данные и сравнивает их с сохранённой версией.
  3. Запись (фаза записи). Если версии совпадают (то есть данные не были изменены другими транзакциями), изменения фиксируются. Если версии различаются, транзакция откатывается и может быть повторена с новыми данными.

Механизмы реализации

Существует несколько способов реализации проверки версий данных:

Версионирование строк

Наиболее распространённый метод. В таблицу базы данных добавляется отдельное поле (например, version целочисленного типа или last_modified с временной меткой). При каждом обновлении записи значение этого поля автоматически увеличивается или обновляется. Условие обновления (UPDATE ... WHERE id = ? AND version = ?) гарантирует, что изменения будут применены только к той версии строки, которая была прочитана. Если количество затронутых строк равно нулю, значит, версия изменилась, и транзакция конфликтует.

Временные метки

Вместо номера версии используется временная метка последнего изменения. Проверка выполняется аналогично: перед обновлением система убеждается, что временная метка в базе данных совпадает с той, что была прочитана транзакцией.

Контрольные суммы (хеши)

Для каждой записи вычисляется хеш (например, MD5 или SHA-256) от её содержимого. При обновлении сравниваются текущий хеш и хеш, вычисленный при чтении. Этот метод менее распространён из-за вычислительных затрат, но может применяться в системах, где версионирование нежелательно.

Сравнение с пессимистичными блокировками

Оптимистичные блокировки противопоставляются пессимистичным блокировкам (англ. pessimistic locking), при которых ресурс блокируется на всё время выполнения транзакции, предотвращая доступ других транзакций.

ХарактеристикаОптимистичная блокировкаПессимистичная блокировка
Время блокировкиТолько на момент записиНа всё время транзакции
ПредположениеКонфликты редкиКонфликты часты
Производительность при низкой конкуренцииВысокаяНизкая (из-за накладных расходов на блокировки)
Производительность при высокой конкуренцииНизкая (частые откаты)Высокая (стабильное выполнение)
Риск взаимоблокировок (deadlock)ОтсутствуетВозможен
Сложность реализацииНизкаяСредняя

Области применения

Оптимистичные блокировки наиболее эффективны в сценариях, где:

  • Низкая конкуренция. Большинство пользователей работают с разными записями, и вероятность одновременного изменения одного и того же объекта мала. Примеры: веб-сайты с большим количеством чтения и редким обновлением данных (форумы, каталоги), системы управления контентом (CMS) при редактировании разных страниц.
  • Короткие транзакции. Транзакции, которые быстро выполняются и редко конфликтуют, выигрывают от отсутствия накладных расходов на блокировку.
  • Системы с высокой нагрузкой на чтение. В системах, где операции чтения значительно преобладают над записью, оптимистичные блокировки позволяют избежать блокировок, снижающих пропускную способность.

Недостатки и ограничения

  • Откаты при высокой конкуренции. Если множество транзакций одновременно пытаются изменить одни и те же данные, частота откатов резко возрастает, что может привести к снижению производительности и «голоданию» некоторых транзакций (они могут бесконечно повторяться, каждый раз конфликтуя).
  • Необходимость повторной обработки. Приложение должно быть спроектировано так, чтобы корректно обрабатывать откаты и повторять транзакции. Это усложняет код, особенно в распределённых системах.
  • Неприменимость для длительных транзакций. При длительном удержании данных (например, при редактировании документа человеком) вероятность конфликта возрастает, и оптимистичная блокировка становится неэффективной. В таких случаях часто применяют стратегию «блокировка по требованию» (pessimistic locking) или «блокировка через версионирование с уведомлением пользователя».
  • Проблема «потерянного обновления». В некоторых реализациях, если не использовать версионирование, возможна ситуация, когда две транзакции одновременно читают данные, затем обе записывают свои изменения, и последняя запись перезаписывает первую без уведомления о конфликте. Корректная реализация оптимистичной блокировки (с проверкой версии) предотвращает этот сценарий.

Пример в веб-приложениях

В типичном веб-приложении (например, на платформах «1С-Битрикс» или «Laravel») оптимистичные блокировки реализуются следующим образом:

  1. Пользователь открывает форму редактирования записи. Система загружает данные вместе с полем version (например, version = 5).
  2. Пользователь вносит изменения и отправляет форму.
  3. Сервер выполняет запрос: UPDATE articles SET title = ?, content = ?, version = version + 1 WHERE id = ? AND version = 5.
  4. Если другой пользователь успел изменить эту же запись (и версия стала 6), то условие WHERE не сработает, и запрос затронет 0 строк. Сервер возвращает ошибку «Конфликт версий» и предлагает пользователю обновить форму и повторить попытку.

Критика и альтернативы

Критика оптимистичных блокировок в основном связана с тем, что они не решают проблему долгосрочных конфликтов в человеко-ориентированных процессах (например, при совместном редактировании документов). В таких случаях применяются:

  • Пессимистичные блокировки — для гарантии эксклюзивного доступа.
  • Слияние (merge) — как в системах контроля версий (Git), где конфликты разрешаются автоматически или вручную.
  • Операциональные преобразования (OT) — технология, лежащая в основе Google Docs и других систем реального времени, где изменения объединяются на уровне отдельных операций.

В российском контексте оптимистичные блокировки активно используются в таких системах, как «1С:Предприятие» (в режиме управляемых блокировок) и в фреймворках для веб-разработки (например, Yii2, Symfony), где они являются стандартным механизмом защиты от конкурентного доступа.

Источники

  1. Gray, J., & Reuter, A. (1993). Transaction Processing: Concepts and Techniques. Morgan Kaufmann.
  2. Bernstein, P. A., Hadzilacos, V., & Goodman, N. (1987). Concurrency Control and Recovery in Database Systems. Addison-Wesley.
  3. Документация по управлению транзакциями в СУБД PostgreSQL (раздел «Уровни изоляции транзакций»).
  4. Документация по фреймворку Laravel (раздел «Eloquent: Mutators & Casting» — примеры оптимистичной блокировки).
  5. Статья «Оптимистичная блокировка» в энциклопедии «Википедия» (русскоязычный раздел).
Заметили ошибку или не согласны с информацией в статье? Напишите нам support@bfometr.ru