Оптимистичная блокировка
Оптимистичная блокировка (англ. optimistic locking) — это механизм управления конкурентным доступом к данным в системах управления базами данных (СУБД) и информационных системах, при котором предполагается, что конфликты между параллельными транзакциями возникают редко. В отличие от пессимистичной блокировки, где данные блокируются на время выполнения транзакции, оптимистичная блокировка не блокирует ресурс заранее, а проверяет отсутствие конфликтов непосредственно перед фиксацией изменений. Если конфликт обнаружен (например, другой пользователь изменил те же данные), транзакция откатывается и может быть повторена.
Принцип работы
Основная идея оптимистичной блокировки заключается в том, что система не препятствует одновременному чтению и редактированию данных несколькими пользователями, а проверяет целостность данных только в момент их сохранения. Этот подход эффективен в сценариях, где количество одновременных изменений одного и того же набора данных невелико, а большинство операций — это чтение.
Процесс работы оптимистичной блокировки обычно включает три этапа:
- Чтение (Read): Пользователь или приложение считывает текущие данные, включая их версию (например, номер версии, метку времени или хеш-сумму).
- Редактирование (Edit): Пользователь вносит изменения в локальную копию данных. В это время другие пользователи могут также читать и редактировать те же данные.
- Проверка и запись (Check and Write): Перед сохранением изменений система повторно считывает версию данных из базы. Если версия, считанная на шаге 1, совпадает с текущей версией в базе, это означает, что никто не изменил данные за время работы пользователя. В этом случае изменения сохраняются, а версия данных увеличивается. Если версии не совпадают, это означает, что другой пользователь уже изменил эти данные, и возникает конфликт. В этом случае текущая транзакция откатывается, и пользователю предлагается разрешить конфликт (например, повторно загрузить актуальные данные и применить свои изменения заново).
Способы реализации
Существует несколько распространённых способов реализации оптимистичной блокировки:
Версионирование строк
Наиболее распространённый метод. В таблицу базы данных добавляется дополнительное поле, например, version (целое число) или last_modified (метка времени). При каждом обновлении записи значение этого поля автоматически увеличивается (или обновляется). Условие обновления (WHERE) включает проверку старого значения версии.
Пример SQL-запроса: ``sql UPDATE products SET name = 'Новое название', version = version + 1 WHERE id = 123 AND version = 5; ` Если за время между чтением и записью другой пользователь изменил запись, версия станет равной 6, и запрос не обновит ни одной строки (0 rows affected`). Приложение может интерпретировать это как сигнал о конфликте.
Хеширование всех полей
Вместо отдельного поля версии можно вычислять хеш-сумму (например, MD5 или SHA1) от всех или выбранных полей записи. Перед обновлением хеш пересчитывается и сравнивается с сохранённым. Этот метод более надёжен, так как учитывает изменение любого поля, но может быть более затратным по вычислительным ресурсам.
Метки времени
Используется поле с меткой времени последнего изменения (updated_at). При обновлении проверяется, что метка времени в базе совпадает с той, что была считана пользователем. Этот метод чувствителен к точности синхронизации часов на серверах.
Преимущества и недостатки
Преимущества
- Высокая производительность при чтении: Отсутствие блокировок позволяет большому числу пользователей одновременно читать данные без задержек.
- Отсутствие взаимных блокировок (deadlocks): Поскольку блокировки не удерживаются, риск возникновения взаимоблокировок значительно снижается.
- Масштабируемость: Оптимистичная блокировка хорошо подходит для распределённых систем и веб-приложений, где транзакции могут быть короткими, а время удержания блокировки — непредсказуемым.
- Простота реализации: В большинстве современных ORM (Object-Relational Mapping) фреймворков (например, Hibernate, Entity Framework, Django ORM) оптимистичная блокировка поддерживается «из коробки» и требует лишь настройки поля версии.
Недостатки
- Снижение производительности при высокой конкуренции: Если конфликты возникают часто, большое количество транзакций будет откатываться и повторяться, что может привести к снижению общей производительности и «голоданию» некоторых пользователей.
- Необходимость обработки конфликтов: Разработчик должен предусмотреть логику обработки конфликтов на стороне приложения (например, уведомить пользователя, предложить объединить изменения или отменить его правки).
- Сложность разрешения конфликтов: В сложных сценариях, когда несколько пользователей редактируют разные части одного документа, автоматическое разрешение конфликтов может быть нетривиальной задачей.
- Не подходит для длительных транзакций: Чем дольше пользователь держит данные открытыми для редактирования, тем выше вероятность конфликта.
Применение
Оптимистичная блокировка широко применяется в:
- Веб-приложениях и CMS: Системы управления контентом (например, WordPress, Joomla), где несколько редакторов могут одновременно работать с разными статьями или страницами.
- Системах совместной работы: Редакторы документов (Google Docs, OnlyOffice), системы управления проектами (Trello, Jira), где пользователи редко редактируют один и тот же объект одновременно.
- Электронной коммерции: Интернет-магазины, где несколько покупателей могут просматривать один и тот же товар, но вероятность одновременного оформления заказа на последний экземпляр относительно невысока.
- Мобильных приложениях: Приложения, работающие в офлайн-режиме, где данные синхронизируются с сервером периодически. Оптимистичная блокировка позволяет выявить конфликты, возникшие во время отсутствия связи.
Сравнение с пессимистичной блокировкой
| Характеристика | Оптимистичная блокировка | Пессимистичная блокировка |
|---|---|---|
| Предположение | Конфликты редки | Конфликты часты |
| Блокировка | Не блокирует данные | Блокирует данные на время транзакции |
| Производительность при чтении | Высокая | Низкая (ожидание блокировки) |
| Риск взаимоблокировок | Низкий | Высокий |
| Обработка конфликтов | Откат и повтор транзакции | Ожидание освобождения блокировки |
| Применение | Среда с преобладанием чтения | Среда с интенсивной записью |
Критика
Основная критика оптимистичной блокировки связана с тем, что она переносит сложность обработки конфликтов на уровень приложения. В системах с высокой конкуренцией за данные (например, системы бронирования авиабилетов или биржевые торговые системы) постоянные откаты транзакций могут сделать систему практически неработоспособной. В таких случаях предпочтительнее использовать пессимистичную блокировку или другие механизмы, такие как очереди сообщений. Кроме того, в распределённых системах, где данные могут реплицироваться с задержкой, оптимистичная блокировка может не гарантировать полной согласованности данных (eventual consistency).
Интересные факты
- Термин «оптимистичная блокировка» был введён в 1970-х годах в контексте ранних реляционных баз данных, но широкое распространение получил с развитием веб-приложений и ORM-фреймворков.
- Некоторые СУБД, такие как PostgreSQL, реализуют механизм MVCC (Multi-Version Concurrency Control), который по своей сути является разновидностью оптимистичной блокировки, но на уровне системы, а не приложения.
- В системах контроля версий (например, Git) также используется подход, напоминающий оптимистичную блокировку: каждый разработчик работает со своей локальной копией, а конфликты разрешаются при слиянии (merge) изменений.
Источники
- Э. Таненбаум, М. ван Стеен. «Распределенные системы. Принципы и парадигмы».
- Г. Гарсия-Молина, Дж. Ульман, Дж. Уидом. «Системы баз данных. Полный курс».
- Документация Hibernate (Java ORM) по оптимистичной блокировке.
- Документация Entity Framework Core (Microsoft) по управлению конкурентностью.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →