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

Пессимистическая блокировка

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

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

Пессимистическая блокировка основана на предположении, что одновременный доступ к одним и тем же данным со стороны разных пользователей или процессов приведёт к конфликту. Поэтому, прежде чем начать изменение данных, транзакция запрашивает у СУБД блокировку на определённый ресурс. Если блокировка успешно получена, другие транзакции не могут читать или изменять заблокированные данные до тех пор, пока блокировка не будет снята. Снятие блокировки происходит при завершении транзакции — либо при её успешной фиксации (COMMIT), либо при откате (ROLLBACK).

Типы блокировок

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

  • Исключительная блокировка (Exclusive Lock, X-lock). Наиболее строгий тип. Накладывается на ресурс, который транзакция намерена изменять (обновлять, удалять, вставлять). Пока действует исключительная блокировка, никакая другая транзакция не может получить ни исключительную, ни разделяемую блокировку на этот же ресурс. Это гарантирует, что только одна транзакция в любой момент времени может модифицировать данные.
  • Разделяемая блокировка (Shared Lock, S-lock). Накладывается на ресурс, который транзакция только читает. Разделяемые блокировки совместимы друг с другом: несколько транзакций могут одновременно читать одни и те же данные. Однако, если на ресурсе установлена разделяемая блокировка, ни одна транзакция не может получить на него исключительную блокировку до тех пор, пока все разделяемые блокировки не будут сняты.
  • Блокировка с намерением (Intent Lock). Используется для организации иерархической блокировки на уровне таблиц и страниц. Например, транзакция, намеревающаяся заблокировать строку в таблице, сначала устанавливает намерение на уровне таблицы. Это позволяет СУБД эффективно проверять совместимость блокировок без сканирования всех строк.

Уровни изоляции транзакций

Пессимистическая блокировка является основным механизмом для реализации высоких уровней изоляции транзакций, определённых стандартом SQL. Чем выше уровень изоляции, тем больше блокировок накладывается и тем дольше они удерживаются, что снижает производительность, но повышает целостность данных.

  • READ UNCOMMITTED (чтение неподтверждённых данных). Блокировки практически не используются. Транзакция может читать данные, изменённые другой незавершённой транзакцией («грязное чтение»). Пессимистический подход здесь не применяется.
  • READ COMMITTED (чтение подтверждённых данных). Стандартный уровень для многих СУБД (например, PostgreSQL, Oracle, Microsoft SQL Server по умолчанию). Исключительные блокировки удерживаются до конца транзакции, а разделяемые блокировки снимаются сразу после выполнения операции чтения. Это предотвращает «грязное чтение», но допускает «неповторяющееся чтение» (когда повторное чтение той же строки в рамках одной транзакции даёт разные результаты) и «фантомное чтение».
  • REPEATABLE READ (повторяемое чтение). Разделяемые блокировки удерживаются до конца транзакции. Это гарантирует, что повторное чтение той же строки в рамках одной транзакции вернёт те же данные, что и при первом чтении. Однако «фантомное чтение» (появление новых строк, соответствующих условию запроса, вставленных другой транзакцией) всё ещё возможно.
  • SERIALIZABLE (сериализуемый). Самый строгий уровень. Обеспечивает полную изоляцию транзакций, имитируя их последовательное выполнение. Для предотвращения «фантомов» используются блокировки диапазона (range locks) или блокировки на уровне таблицы. Этот уровень наиболее ресурсоёмкий и часто приводит к взаимоблокировкам.

Преимущества и недостатки

Преимущества

  • Гарантированная целостность данных. При правильной настройке пессимистическая блокировка полностью исключает конфликты одновременного доступа, такие как потерянные обновления, «грязное», «неповторяющееся» и «фантомное» чтение.
  • Простота модели для разработчика. Разработчику не нужно заботиться о проверке версий данных или обработке ошибок конфликтов при фиксации, как в случае с оптимистической блокировкой. Система сама управляет доступом.
  • Предсказуемость. Поведение системы при высокой конкуренции за ресурсы является детерминированным: транзакции выстраиваются в очередь и выполняются последовательно.

Недостатки

  • Снижение производительности. Наложение и снятие блокировок требуют дополнительных вычислительных ресурсов. Чем дольше удерживается блокировка, тем дольше другие транзакции вынуждены ждать, что снижает пропускную способность системы.
  • Риск взаимоблокировок (deadlocks). Ситуация, когда две или более транзакции удерживают блокировки, необходимые друг другу, и ни одна не может продолжить выполнение. СУБД обычно разрешает взаимоблокировки, принудительно откатывая одну из транзакций («жертву»), что приводит к потере её работы.
  • Масштабируемость. Пессимистическая блокировка плохо масштабируется в системах с большим количеством одновременных пользователей, особенно при выполнении длительных транзакций. Она эффективна при низкой или средней конкуренции, но при высокой нагрузке может стать узким местом.

Применение

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

  • Финансовые системы. Обработка банковских транзакций, списание средств со счетов, резервирование билетов. Здесь недопустима ситуация, когда два процесса одновременно спишут одну и ту же сумму.
  • Системы бронирования. Бронирование мест в самолётах, гостиницах, на концертах. Пока пользователь оформляет заказ, выбранные места блокируются, чтобы их не мог занять другой клиент.
  • ERP-системы. Управление запасами, где необходимо точно знать остатки товаров на складе в реальном времени.
  • Редакторы документов с совместным доступом. В некоторых системах, чтобы избежать конфликтов при одновременном редактировании одного документа, весь документ или его часть блокируется для других пользователей на время работы одного редактора.

Реализация в популярных СУБД

  • PostgreSQL. По умолчанию использует оптимистическую блокировку на основе механизма многоверсионности (MVCC). Однако для принудительного использования пессимистической блокировки можно использовать команду SELECT ... FOR UPDATE (исключительная блокировка) или SELECT ... FOR SHARE (разделяемая блокировка).
  • MySQL (InnoDB). Активно использует пессимистические блокировки на уровне строк. Команда SELECT ... FOR UPDATE также доступна. InnoDB поддерживает все четыре уровня изоляции, причём REPEATABLE READ является уровнем по умолчанию.
  • Oracle Database. Использует MVCC для чтения, но при записи накладывает исключительные блокировки. Для явного указания пессимистической блокировки применяется конструкция SELECT ... FOR UPDATE.
  • Microsoft SQL Server. Предоставляет полный набор механизмов блокировок, включая блокировки строк, страниц, таблиц и баз данных. Управление блокировками настраивается через уровни изоляции и хинты (например, WITH (UPDLOCK, HOLDLOCK)).

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

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

Выбор между двумя подходами зависит от характера нагрузки:

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

Источники

  1. Гектор Гарсия-Молина, Джеффри Д. Ульман, Дженнифер Уидом. «Системы баз данных. Полный курс». — М.: Вильямс, 2003.
  2. К. Дж. Дейт. «Введение в системы баз данных». — М.: Вильямс, 2005.
  3. Документация PostgreSQL: «Concurrency Control» (Chapter 13).
  4. Документация MySQL: «InnoDB Locking and Transaction Model».
  5. Документация Microsoft SQL Server: «Transaction Locking and Row Versioning Guide».

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

На главную BFOmetr →