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

Блокировка записи

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

Назначение и принцип работы

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

Принцип работы блокировки записи заключается в следующем:

  1. Процесс, желающий изменить данные, запрашивает блокировку записи у СУБД.
  2. Если блокировка записи на данный ресурс не установлена другим процессом, СУБД предоставляет её, и процесс получает исключительное право на изменение.
  3. Другие процессы, пытающиеся установить блокировку записи на тот же ресурс, ставятся в очередь ожидания до освобождения блокировки.
  4. После завершения операции записи процесс снимает блокировку, и следующий процесс из очереди получает доступ.

Важно различать блокировку записи и блокировку чтения (shared lock). Блокировка чтения позволяет нескольким процессам одновременно читать данные, но запрещает их изменение. Блокировка записи, напротив, запрещает как запись, так и чтение (в большинстве СУБД) со стороны других процессов, чтобы избежать чтения «грязных» данных (dirty read).

Виды блокировок записи

Блокировки записи классифицируются по различным признакам.

По уровню гранулярности

  • Блокировка строки (row-level lock) — блокируется только одна запись (строка таблицы). Наиболее гибкий и производительный вариант, используемый в современных СУБД (PostgreSQL, MySQL с движком InnoDB, Oracle).
  • Блокировка страницы (page-level lock) — блокируется блок данных (страница), содержащий несколько строк. Менее гранулярный, но может быть эффективнее при работе с большими объёмами данных в некоторых СУБД (например, в старых версиях Microsoft SQL Server).
  • Блокировка таблицы (table-level lock) — блокируется вся таблица. Простая в реализации, но сильно снижает параллелизм. Используется в СУБД с простыми механизмами (MyISAM для MySQL) или при выполнении массовых операций (например, ALTER TABLE).
  • Блокировка базы данных (database-level lock) — блокируется вся база данных. Крайне редкая, применяется только в специализированных системах.

По способу реализации

  • Пессимистичная блокировка (pessimistic locking) — блокировка устанавливается до начала операции записи и удерживается до её завершения. Предполагает, что конфликты вероятны, и предотвращает их заранее. Используется в высоконагруженных транзакционных системах.
  • Оптимистичная блокировка (optimistic locking) — блокировка не устанавливается в момент начала операции. Вместо этого перед записью проверяется, не изменились ли данные с момента их чтения (обычно с помощью версии записи или временной метки). Если данные были изменены другим процессом, транзакция откатывается и повторяется. Используется в системах с низкой вероятностью конфликтов (например, веб-приложениях).

По времени удержания

  • Краткосрочная блокировка (short-duration lock) — удерживается только на время выполнения одной операции (например, UPDATE). Типична для пессимистичных блокировок.
  • Долгосрочная блокировка (long-duration lock) — удерживается на время всей транзакции. Обеспечивает более строгую изоляцию, но снижает параллелизм.

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

PostgreSQL

PostgreSQL использует многовариантную модель управления параллельным доступом (MVCC), которая позволяет избежать многих конфликтов без явных блокировок. Однако блокировки записи всё же применяются:

  • Блокировка строки на запись (RowExclusiveLock) — устанавливается при выполнении команд UPDATE, DELETE, INSERT.
  • Блокировка таблицы — может быть установлена явно через команду LOCK TABLE (например, ACCESS EXCLUSIVE для полной блокировки).
  • Оптимистичная блокировка реализуется через проверку поля xmin (идентификатор транзакции, создавшей версию строки).

MySQL (InnoDB)

InnoDB поддерживает блокировки на уровне строк с использованием механизма блокировок на основе индексов:

  • Record lock — блокировка одной записи индекса.
  • Gap lock — блокировка промежутка между записями индекса (предотвращает фантомное чтение).
  • Next-key lock — комбинация record lock и gap lock.
  • Блокировка таблицы — в InnoDB возможна, но не рекомендуется для обычных операций.

Microsoft SQL Server

SQL Server поддерживает блокировки на уровне строк, страниц и таблиц. Механизм блокировок динамически выбирает уровень гранулярности в зависимости от количества затрагиваемых строк. Блокировки записи могут быть эксклюзивными (X) или обновляемыми (U), причём U-блокировка позволяет избежать взаимоблокировок при чтении с намерением записи.

Oracle Database

Oracle использует MVCC и блокировки на уровне строк. Блокировка записи устанавливается только на изменяемые строки и не блокирует чтение (читатели не ждут писателей). Это достигается за счёт хранения старых версий данных в сегментах отката (undo segments).

Проблемы, связанные с блокировками записи

Взаимоблокировка (deadlock)

Ситуация, когда два или более процессов блокируют друг друга, ожидая освобождения ресурсов, занятых другими процессами. Например:

  • Процесс A блокирует строку 1 и ждёт строку 2.
  • Процесс B блокирует строку 2 и ждёт строку 1.

СУБД автоматически обнаруживает взаимоблокировки и прерывает одну из транзакций (обычно с откатом).

Голодание (starvation)

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

Снижение производительности

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

Применение в файловых системах

В файловых системах (например, NTFS, ext4) блокировка записи используется для предотвращения одновременного изменения файла несколькими процессами. Реализуется через системные вызовы (например, flock в Linux, LockFileEx в Windows). Блокировка может быть обязательной (mandatory) — операционная система принудительно блокирует доступ, или рекомендательной (advisory) — процессы должны добровольно проверять блокировку.

Примеры использования

  • Банковские системы: при переводе средств блокировка записи на счёте предотвращает одновременное списание и зачисление, что могло бы привести к некорректному балансу.
  • Системы бронирования: блокировка записи на билет или номер в гостинице гарантирует, что один и тот же ресурс не будет продан дважды.
  • Редакторы кода с совместным доступом: блокировка записи на файл предотвращает конфликты при одновременном редактировании.

Интересные факты

  • В СУБД, использующих MVCC, блокировка записи не блокирует чтение (читатели видят старую версию данных), что значительно повышает параллелизм.
  • В распределённых системах (например, Apache Cassandra, Amazon DynamoDB) блокировки записи реализуются через консенсусные протоколы (Paxos, Raft) или механизмы «последняя запись побеждает» (last-write-wins).
  • В некоторых базах данных (например, SQLite) блокировка записи может быть на уровне всей базы данных, что делает её непригодной для высоконагруженных многопользовательских приложений.

Источники

  • Теория баз данных: учебник / К. Дж. Дейт. — М.: Вильямс, 2016.
  • PostgreSQL Documentation: Chapter 13. Concurrency Control.
  • MySQL 8.0 Reference Manual: InnoDB Locking.
  • Microsoft SQL Server Documentation: Locking in the Database Engine.
  • Oracle Database Concepts: Data Concurrency and Consistency.

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

На главную BFOmetr →