Оптимистичные блокировки
Оптимистичные блокировки (англ. optimistic locking) — это механизм управления конкурентным доступом к данным в информационных системах, при котором блокировка ресурса не накладывается на время выполнения транзакции, а проверка на конфликты выполняется непосредственно перед фиксацией изменений. Данный подход предполагает, что конфликты между параллельными транзакциями возникают редко (отсюда название «оптимистичный»), и поэтому накладные расходы на предварительную блокировку считаются избыточными. В случае обнаружения конфликта (например, изменения данных другой транзакцией) текущая транзакция откатывается и повторяется.
Принцип работы
Оптимистичные блокировки основаны на предположении, что большинство операций чтения и записи не пересекаются. Вместо того чтобы запрещать другим транзакциям доступ к данным на время выполнения, система позволяет всем транзакциям работать параллельно, но перед записью проверяет, не изменились ли данные с момента их чтения.
Процесс выполнения транзакции с оптимистичной блокировкой включает три этапа:
- Чтение (фаза чтения). Транзакция считывает данные и запоминает их текущее состояние (обычно в виде версии, временной метки или контрольной суммы). Никаких блокировок на этом этапе не накладывается.
- Вычисление (фаза проверки). Транзакция выполняет необходимые вычисления и готовит изменения. Перед записью она повторно считывает исходные данные и сравнивает их с сохранённой версией.
- Запись (фаза записи). Если версии совпадают (то есть данные не были изменены другими транзакциями), изменения фиксируются. Если версии различаются, транзакция откатывается и может быть повторена с новыми данными.
Механизмы реализации
Существует несколько способов реализации проверки версий данных:
Версионирование строк
Наиболее распространённый метод. В таблицу базы данных добавляется отдельное поле (например, version целочисленного типа или last_modified с временной меткой). При каждом обновлении записи значение этого поля автоматически увеличивается или обновляется. Условие обновления (UPDATE ... WHERE id = ? AND version = ?) гарантирует, что изменения будут применены только к той версии строки, которая была прочитана. Если количество затронутых строк равно нулю, значит, версия изменилась, и транзакция конфликтует.
Временные метки
Вместо номера версии используется временная метка последнего изменения. Проверка выполняется аналогично: перед обновлением система убеждается, что временная метка в базе данных совпадает с той, что была прочитана транзакцией.
Контрольные суммы (хеши)
Для каждой записи вычисляется хеш (например, MD5 или SHA-256) от её содержимого. При обновлении сравниваются текущий хеш и хеш, вычисленный при чтении. Этот метод менее распространён из-за вычислительных затрат, но может применяться в системах, где версионирование нежелательно.
Сравнение с пессимистичными блокировками
Оптимистичные блокировки противопоставляются пессимистичным блокировкам (англ. pessimistic locking), при которых ресурс блокируется на всё время выполнения транзакции, предотвращая доступ других транзакций.
| Характеристика | Оптимистичная блокировка | Пессимистичная блокировка |
|---|---|---|
| Время блокировки | Только на момент записи | На всё время транзакции |
| Предположение | Конфликты редки | Конфликты часты |
| Производительность при низкой конкуренции | Высокая | Низкая (из-за накладных расходов на блокировки) |
| Производительность при высокой конкуренции | Низкая (частые откаты) | Высокая (стабильное выполнение) |
| Риск взаимоблокировок (deadlock) | Отсутствует | Возможен |
| Сложность реализации | Низкая | Средняя |
Области применения
Оптимистичные блокировки наиболее эффективны в сценариях, где:
- Низкая конкуренция. Большинство пользователей работают с разными записями, и вероятность одновременного изменения одного и того же объекта мала. Примеры: веб-сайты с большим количеством чтения и редким обновлением данных (форумы, каталоги), системы управления контентом (CMS) при редактировании разных страниц.
- Короткие транзакции. Транзакции, которые быстро выполняются и редко конфликтуют, выигрывают от отсутствия накладных расходов на блокировку.
- Системы с высокой нагрузкой на чтение. В системах, где операции чтения значительно преобладают над записью, оптимистичные блокировки позволяют избежать блокировок, снижающих пропускную способность.
Недостатки и ограничения
- Откаты при высокой конкуренции. Если множество транзакций одновременно пытаются изменить одни и те же данные, частота откатов резко возрастает, что может привести к снижению производительности и «голоданию» некоторых транзакций (они могут бесконечно повторяться, каждый раз конфликтуя).
- Необходимость повторной обработки. Приложение должно быть спроектировано так, чтобы корректно обрабатывать откаты и повторять транзакции. Это усложняет код, особенно в распределённых системах.
- Неприменимость для длительных транзакций. При длительном удержании данных (например, при редактировании документа человеком) вероятность конфликта возрастает, и оптимистичная блокировка становится неэффективной. В таких случаях часто применяют стратегию «блокировка по требованию» (pessimistic locking) или «блокировка через версионирование с уведомлением пользователя».
- Проблема «потерянного обновления». В некоторых реализациях, если не использовать версионирование, возможна ситуация, когда две транзакции одновременно читают данные, затем обе записывают свои изменения, и последняя запись перезаписывает первую без уведомления о конфликте. Корректная реализация оптимистичной блокировки (с проверкой версии) предотвращает этот сценарий.
Пример в веб-приложениях
В типичном веб-приложении (например, на платформах «1С-Битрикс» или «Laravel») оптимистичные блокировки реализуются следующим образом:
- Пользователь открывает форму редактирования записи. Система загружает данные вместе с полем
version(например,version = 5). - Пользователь вносит изменения и отправляет форму.
- Сервер выполняет запрос:
UPDATE articles SET title = ?, content = ?, version = version + 1 WHERE id = ? AND version = 5. - Если другой пользователь успел изменить эту же запись (и версия стала
6), то условиеWHEREне сработает, и запрос затронет 0 строк. Сервер возвращает ошибку «Конфликт версий» и предлагает пользователю обновить форму и повторить попытку.
Критика и альтернативы
Критика оптимистичных блокировок в основном связана с тем, что они не решают проблему долгосрочных конфликтов в человеко-ориентированных процессах (например, при совместном редактировании документов). В таких случаях применяются:
- Пессимистичные блокировки — для гарантии эксклюзивного доступа.
- Слияние (merge) — как в системах контроля версий (Git), где конфликты разрешаются автоматически или вручную.
- Операциональные преобразования (OT) — технология, лежащая в основе Google Docs и других систем реального времени, где изменения объединяются на уровне отдельных операций.
В российском контексте оптимистичные блокировки активно используются в таких системах, как «1С:Предприятие» (в режиме управляемых блокировок) и в фреймворках для веб-разработки (например, Yii2, Symfony), где они являются стандартным механизмом защиты от конкурентного доступа.
Источники
- Gray, J., & Reuter, A. (1993). Transaction Processing: Concepts and Techniques. Morgan Kaufmann.
- Bernstein, P. A., Hadzilacos, V., & Goodman, N. (1987). Concurrency Control and Recovery in Database Systems. Addison-Wesley.
- Документация по управлению транзакциями в СУБД PostgreSQL (раздел «Уровни изоляции транзакций»).
- Документация по фреймворку Laravel (раздел «Eloquent: Mutators & Casting» — примеры оптимистичной блокировки).
- Статья «Оптимистичная блокировка» в энциклопедии «Википедия» (русскоязычный раздел).
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →