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

Блокировка на уровне записей

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

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

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

В 1970–1980-х годах с развитием теории транзакций и требований ACID (атомарность, согласованность, изоляция, долговечность) возникла необходимость в более гранулированных механизмах блокировки. Первой коммерческой СУБД, реализовавшей блокировку на уровне записей, стала IBM DB2 (1983 год). Впоследствии этот механизм был внедрён в Oracle (1986), Microsoft SQL Server (1989), PostgreSQL (1996) и другие современные СУБД.

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

Блокировка на уровне записей реализуется через менеджер блокировок (lock manager) — компонент СУБД, который отслеживает, какие строки заблокированы и какими транзакциями. Каждая блокировка хранится в памяти в виде записи, содержащей идентификатор транзакции, идентификатор строки (обычно через физический адрес или первичный ключ) и тип блокировки.

Типы блокировок записей

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

При попытке транзакции получить блокировку СУБД проверяет, не конфликтует ли запрашиваемая блокировка с уже существующими. Конфликт возникает, если:

При обнаружении конфликта транзакция либо переводится в состояние ожидания (до снятия конфликтующей блокировки), либо немедленно завершается с ошибкой (в зависимости от настроек тайм-аута или политики обнаружения взаимоблокировок).

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

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

Недостатки

Сравнение с другими уровнями блокировки

Уровень блокировкиГранулярностьПараллелизмНакладные расходыТипичные СУБД
Таблица (table)Вся таблицаНизкийМинимальныеMyISAM (MySQL), ранние версии
Страница (page)Блок данных (4–32 КБ)СреднийСредниеSQL Server (по умолчанию), Oracle (опционально)
Запись (row)Одна строкаВысокийВысокиеInnoDB (MySQL), PostgreSQL, Oracle, DB2

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

MySQL (InnoDB)

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

PostgreSQL

PostgreSQL использует MVCC для обеспечения изоляции без блокировок на чтение. Блокировка на уровне записей применяется только при явных операциях SELECT ... FOR UPDATE, SELECT ... FOR NO KEY UPDATE и при изменении данных (UPDATE, DELETE). PostgreSQL поддерживает несколько режимов блокировок, включая FOR SHARE и FOR KEY SHARE, а также автоматическое обнаружение взаимоблокировок.

Oracle Database

Oracle применяет блокировку на уровне записей как часть своей архитектуры без блокировок на чтение (readers never block writers). При изменении строки накладывается исключительная блокировка, которая снимается только при фиксации или откате транзакции. Oracle не поддерживает разделяемые блокировки на уровне записей — чтение всегда неблокирующее.

Microsoft SQL Server

SQL Server по умолчанию использует блокировку на уровне страниц (8 КБ), но может автоматически повышать гранулярность до строк при обнаружении конфликтов. Поддерживает все основные типы блокировок, а также механизм эскалации блокировок (lock escalation), при котором множество блокировок строк заменяется одной блокировкой таблицы для снижения накладных расходов.

Влияние на производительность

Эффективность блокировки на уровне записей зависит от характера рабочей нагрузки:

Для снижения накладных расходов СУБД применяют:

Критика и ограничения

Несмотря на широкое распространение, блокировка на уровне записей не лишена недостатков. В распределённых базах данных (например, Google Spanner, CockroachDB) традиционная блокировка строк заменяется оптимистическим управлением параллелизмом (optimistic concurrency control) или двухфазным подтверждением с использованием часов TrueTime. В высоконагруженных системах (миллионы транзакций в секунду) накладные расходы на менеджер блокировок могут стать критическими, что приводит к необходимости шардирования или перехода на NoSQL-решения без поддержки транзакций ACID.

Источники

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

На главную BFOmetr →