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

Блокировка на уровне строк

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

История и предпосылки появления

До появления блокировки на уровне строк в ранних СУБД (например, в dBase, ранних версиях FoxPro) использовалась преимущественно блокировка на уровне файлов или таблиц. Это означало, что при записи в любую часть таблицы вся таблица становилась недоступной для других пишущих транзакций. С ростом объёмов данных и числа одновременных пользователей такой подход приводил к значительным задержкам и снижению производительности.

Первые реляционные СУБД, такие как Oracle (выпущенная в 1979 году) и IBM DB2, начали внедрять более гранулированные механизмы блокировок. Однако массовое распространение блокировка на уровне строк получила в 1990-х годах с развитием клиент-серверных архитектур и появлением таких СУБД, как Microsoft SQL Server (первая версия — 1989 год, поддержка блокировок строк — с версии 6.0, 1995 год) и PostgreSQL (поддержка блокировок строк с первых версий, 1996 год).

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

Блокировка на уровне строк реализуется через механизмы менеджера блокировок (lock manager) СУБД. При выполнении операции изменения (INSERT, UPDATE, DELETE) или явного указания блокировки (SELECT ... FOR UPDATE) СУБД проверяет, не удерживается ли уже блокировка на данной строке другой транзакцией.

Основные типы блокировок строк

  1. Разделяемая блокировка (Shared lock, S-lock) — накладывается при чтении данных. Другие транзакции также могут читать строку, но не могут её изменять. В некоторых СУБД (например, PostgreSQL) чтение не блокирует запись благодаря механизму многоверсионности (MVCC).
  2. Исключительная блокировка (Exclusive lock, X-lock) — накладывается при записи. Ни одна другая транзакция не может ни читать (в режиме блокировки), ни изменять строку до завершения текущей транзакции.
  3. Блокировка намерения (Intent lock) — вспомогательный тип, указывающий, что транзакция намерена заблокировать строку на более высоком уровне (странице, таблице). Используется для эффективного обнаружения конфликтов между блокировками разных уровней.

Механизм обнаружения конфликтов

СУБД ведёт хеш-таблицу или битовую карту заблокированных строк. При попытке установить блокировку проверяется:

  • Существует ли уже блокировка на данной строке.
  • Совместим ли тип запрашиваемой блокировки с существующей (например, две разделяемые блокировки совместимы, а разделяемая и исключительная — нет).

Если блокировка несовместима, транзакция переводится в состояние ожидания до освобождения блокировки или до истечения тайм-аута.

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

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

  • Высокая степень параллелизма — несколько транзакций могут одновременно изменять разные строки одной таблицы.
  • Минимизация блокировок — блокируется только необходимая запись, а не вся таблица или страница.
  • Снижение вероятности взаимоблокировок (deadlock) — хотя полностью они не исключены, гранулярные блокировки уменьшают количество конфликтных ситуаций по сравнению с блокировками на уровне таблиц.
  • Поддержка длительных транзакций — при работе с большими объёмами данных другие пользователи не блокируются на всё время выполнения транзакции.

Недостатки

  • Накладные расходы на управление — СУБД тратит ресурсы (память и процессорное время) на отслеживание состояния каждой заблокированной строки. При большом количестве строк в одной транзакции (например, массовое обновление) это может привести к перегрузке менеджера блокировок.
  • Эскалация блокировок — при превышении определённого порога (обычно настраиваемого) СУБД может автоматически повысить уровень блокировки до страницы или таблицы. Это происходит, например, при обновлении более 40–50% строк таблицы в Microsoft SQL Server.
  • Взаимоблокировки (deadlock) — хотя их вероятность ниже, они всё же возможны, когда две транзакции удерживают блокировки на строки, необходимые друг другу. СУБД автоматически обнаруживает такие ситуации и принудительно завершает одну из транзакций.
  • Сложность реализации — требует от разработчиков понимания уровней изоляции транзакций и явного управления блокировками (например, через SELECT ... FOR UPDATE).

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

PostgreSQL

Использует механизм многоверсионности (MVCC) для обеспечения изоляции чтения. Блокировки на уровне строк накладываются только на операции записи. Чтение никогда не блокируется записью и наоборот. Исключительная блокировка строки устанавливается при выполнении UPDATE, DELETE или SELECT ... FOR UPDATE.

Oracle

Также применяет MVCC. Блокировки строк устанавливаются исключительно для изменяемых данных. При чтении блокировки не накладываются. Oracle не поддерживает блокировку на уровне страниц, используя только строки и таблицы.

Microsoft SQL Server

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

MySQL (InnoDB)

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

Практические аспекты использования

Когда оправдана блокировка на уровне строк

  • Высоконагруженные OLTP-системы (онлайн-обработка транзакций) — интернет-магазины, банковские системы, биллинг.
  • Системы с большим количеством одновременных пользователей (сотни и тысячи), работающих с одними и теми же таблицами.
  • Приложения, где требуется гарантия целостности данных при параллельном доступе (например, резервирование билетов, бронирование номеров).

Когда следует избегать

  • Пакетная обработка больших объёмов данных — массовые обновления (UPDATE без WHERE по всей таблице) могут привести к эскалации блокировок или перегрузке менеджера блокировок.
  • Системы с преимущественно операциями чтения — в таких случаях блокировки строк могут быть избыточны, и достаточно блокировок на уровне таблиц или использования снэпшотов (snapshot isolation).
  • Системы с очень короткими транзакциями — накладные расходы на установку и снятие блокировок могут превысить выгоду от параллелизма.

Альтернативы

  • Оптимистическая блокировка — не использует блокировки СУБД. Вместо этого приложение проверяет версию строки (через поле timestamp или номер версии) перед записью. Если строка была изменена другой транзакцией, операция откатывается.
  • Блокировка на уровне страниц — блокируется целая страница данных (обычно 4–16 КБ). Компромисс между накладными расходами и степенью параллелизма.
  • Блокировка на уровне таблиц — простая реализация, подходит для небольших таблиц или операций DDL (ALTER TABLE, DROP TABLE).
  • Многоверсионное управление параллелизмом (MVCC) — каждая транзакция видит снэпшот данных на момент своего начала. Блокировки строк используются только для записи.

Источники

  • К. Дж. Дейт. «Введение в системы баз данных», 8-е издание, 2005.
  • PostgreSQL Documentation: Chapter 13. Concurrency Control.
  • Microsoft SQL Server Documentation: Locking in the Database Engine.
  • Oracle Database Concepts: Data Concurrency and Consistency.
  • MySQL 8.0 Reference Manual: InnoDB Locking and Transaction Model.

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

На главную BFOmetr →