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

2PL

2PL (от англ. two-phase locking, двухфазная блокировка) — это механизм управления параллельным доступом к данным в системах управления базами данных (СУБД) и транзакционных системах, обеспечивающий сериализуемость транзакций. Протокол 2PL гарантирует, что одновременное выполнение нескольких транзакций даёт результат, эквивалентный некоторому последовательному (серийному) выполнению тех же транзакций, что предотвращает аномалии согласованности данных, такие как потерянные обновления, «грязное» чтение и неповторяющееся чтение.

История

Концепция блокировок как средства управления параллелизмом возникла в 1970-х годах с развитием реляционных баз данных. В 1976 году К. П. Эбботт и Дж. Д. Ульман впервые формально описали двухфазный протокол блокировок в контексте обеспечения сериализуемости. В 1979 году Филип Бернштейн и Натан Гудман в своей работе «Concurrency Control in Distributed Database Systems» закрепили 2PL как один из основных подходов к управлению параллельным доступом. В 1980-х годах протокол был реализован в коммерческих СУБД, таких как IBM DB2 и Oracle Database, и остаётся стандартным механизмом во многих современных реляционных СУБД (например, PostgreSQL, MySQL с InnoDB).

Основные принципы

Двухфазность

Протокол 2PL делит выполнение транзакции на две фазы:

  1. Фаза захвата блокировок (расширение, growing phase): транзакция может только устанавливать блокировки на объекты данных (строки, таблицы, страницы), но не может снимать уже установленные блокировки.
  2. Фаза освобождения блокировок (сжатие, shrinking phase): транзакция может только снимать блокировки, но не может устанавливать новые.

Переход между фазами происходит в момент, когда транзакция снимает первую блокировку. После этого все последующие операции снятия блокировок выполняются в фазе сжатия, а захват новых блокировок запрещён.

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

В классическом 2PL используются два типа блокировок:

  • Разделяемая блокировка (S-блокировка, shared lock): устанавливается для чтения данных. Несколько транзакций могут одновременно удерживать S-блокировку на одном объекте.
  • Исключительная блокировка (X-блокировка, exclusive lock): устанавливается для записи или изменения данных. Только одна транзакция может удерживать X-блокировку на объекте; другие транзакции не могут установить ни S-, ни X-блокировку на тот же объект.

Совместимость блокировок: S-блокировка совместима с другой S-блокировкой, но несовместима с X-блокировкой; X-блокировка несовместима ни с какой другой блокировкой.

Правила протокола

  1. Транзакция должна установить блокировку на объект перед выполнением операции чтения или записи.
  2. Блокировки снимаются только после завершения фазы захвата.
  3. Если транзакция не может получить блокировку из-за конфликта, она переходит в состояние ожидания до освобождения блокировки другой транзакцией.

Разновидности 2PL

Базовый 2PL (Basic 2PL)

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

Строгий 2PL (Strict 2PL)

Модификация, в которой исключительные блокировки (X-блокировки) удерживаются до конца транзакции (до фиксации или отката). Разделяемые блокировки могут сниматься раньше. Это предотвращает «каскадный откат» (cascading rollback), при котором откат одной транзакции требует отката других транзакций, читавших её незафиксированные данные. Строгий 2PL является наиболее распространённым вариантом в современных СУБД.

Консервативный 2PL (Conservative 2PL)

Транзакция захватывает все необходимые блокировки заранее, до начала выполнения операций. Если какая-либо блокировка недоступна, транзакция не запускается. Это исключает взаимоблокировки, но снижает параллелизм, так как транзакция может ждать блокировок, которые ей не понадобятся, или удерживать блокировки дольше, чем необходимо.

Оптимистичный 2PL (Optimistic 2PL)

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

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

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

  • Гарантированная сериализуемость: при правильной реализации 2PL обеспечивает изоляцию транзакций на уровне сериализуемости, что является наивысшим уровнем изоляции по стандарту SQL.
  • Простота реализации: протокол легко встраивается в существующие СУБД и не требует сложных вычислений.
  • Предсказуемость: поведение транзакций при использовании 2PL хорошо изучено и документировано.

Недостатки

  • Взаимоблокировки: базовый 2PL подвержен deadlocks, что требует механизмов их обнаружения и разрешения (например, тайм-ауты или графы ожидания).
  • Снижение параллелизма: блокировки могут удерживаться длительное время, особенно в строгом 2PL, что снижает пропускную способность системы.
  • Голодание транзакций: транзакция с низким приоритетом может бесконечно долго ждать блокировки, если её постоянно опережают более приоритетные транзакции.
  • Накладные расходы: управление блокировками требует дополнительной памяти и вычислительных ресурсов.

Применение

2PL широко используется в реляционных СУБД для обеспечения изоляции транзакций. Примеры:

  • PostgreSQL использует строгий 2PL для уровней изоляции «Read Committed» и «Repeatable Read», хотя сериализуемость достигается через механизм Serializable Snapshot Isolation (SSI).
  • MySQL (движок InnoDB) применяет строгий 2PL с блокировками на уровне строк.
  • Oracle Database использует оптимистичный подход для чтения (Multiversion Concurrency Control, MVCC), но для записи применяет строгий 2PL.

В распределённых системах 2PL может быть расширен до распределённого 2PL (Distributed 2PL), где блокировки координируются между узлами через менеджер блокировок.

Критика

Основная критика 2PL связана с его производительностью в высоконагруженных системах. Блокировки создают узкие места, особенно при большом числе транзакций, работающих с одними и теми же данными. Альтернативные подходы, такие как многоверсионное управление параллелизмом (MVCC) и оптимистичное управление параллелизмом (OCC), часто предлагают лучшую масштабируемость, хотя и не всегда гарантируют сериализуемость. В современных СУБД 2PL часто комбинируется с MVCC: MVCC обеспечивает неблокирующее чтение, а 2PL — блокировки для записи.

Источники

  • Bernstein, P. A., Hadzilacos, V., & Goodman, N. (1987). Concurrency Control and Recovery in Database Systems. Addison-Wesley.
  • Gray, J., & Reuter, A. (1993). Transaction Processing: Concepts and Techniques. Morgan Kaufmann.
  • Silberschatz, A., Korth, H. F., & Sudarshan, S. (2010). Database System Concepts (6th ed.). McGraw-Hill.
  • Weikum, G., & Vossen, G. (2002). Transactional Information Systems: Theory, Algorithms, and the Practice of Concurrency Control and Recovery. Morgan Kaufmann.

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

На главную BFOmetr →