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

Оптимистичная блокировка

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

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

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

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

  1. Чтение (Read): Пользователь или приложение считывает текущие данные, включая их версию (например, номер версии, метку времени или хеш-сумму).
  2. Редактирование (Edit): Пользователь вносит изменения в локальную копию данных. В это время другие пользователи могут также читать и редактировать те же данные.
  3. Проверка и запись (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 →