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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

В типичном веб-приложении (например, на платформах «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 строк. Сервер возвращает ошибку «Конфликт версий» и предлагает пользователю обновить форму и повторить попытку.

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

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

В российском контексте оптимистичные блокировки активно используются в таких системах, как «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. Статья «Оптимистичная блокировка» в энциклопедии «Википедия» (русскоязычный раздел).

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →