Coding Interview Prep · Урок

Взаимные блокировки, блокировки и MVCC

Как базы данных предотвращают конфликты и чем отличаются блокировки от снимков

Урок 4 из 413 шагов

«Взаимные блокировки, блокировки и MVCC» — бесплатный урок Coding Interview Prep на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Coding Interview Prep, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Coding Interview Prep содержит 4 уроков всего.

Как базы данных фактически обеспечивают изоляцию

Уровни изоляции — это обещание, а блокировки и MVCC — механизмы, которые его выполняют. На собеседовании об этом спрашивают, чтобы понять, представляете ли Вы, что происходит внутри системы, когда транзакции сталкиваются.

Существует две основные стратегии:

  • Пессимистическая (блокировки): блокировать конфликтующий доступ до освобождения блокировки.
  • Оптимистическая / MVCC: позволить всем читать согласованный снимок и выявлять конфликты при фиксации транзакции.

В этом уроке рассматриваются блокировки, взаимные блокировки и MVCC, а также компромиссы между ними.

Разделяемые и эксклюзивные блокировки

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

  • Разделяемая блокировка (S) для чтения. Многие транзакции могут одновременно удерживать разделяемую блокировку одной и той же строки.
  • Эксклюзивная блокировка (X) для записи. Её может удерживать только одна транзакция, и она блокирует все остальные блокировки этой строки.

Правило такое: S совместима с S, а X — ни с чем. Операция записи должна ждать завершения всех операций чтения, а операции чтения — освобождения блокировки записи.

Явные блокировки с SELECT FOR UPDATE

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

SELECT ... FOR UPDATE устанавливает эксклюзивные блокировки строк; строки остаются заблокированными до выполнения COMMIT или ROLLBACK.

BEGIN;
-- lock the row so no one else can modify it concurrently
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;  -- lock released here

Что такое взаимная блокировка

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

Классический случай: T1 блокирует строку A, а затем хочет заблокировать строку B; T2 блокирует строку B, а затем хочет заблокировать строку A. Каждая бесконечно ждёт другую.

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

Взаимная блокировка: временная шкала

Обратите внимание, как пересекается порядок блокировок. T1 блокирует строку 1, а затем запрашивает строку 2; T2 блокирует строку 2, а затем запрашивает строку 1. Ни одна транзакция не освобождает блокировку, поэтому движок прерывает одну из них.

Прерванная транзакция получает ошибку вроде deadlock detected и должна повторить попытку. Оставшаяся транзакция нормально выполняет COMMIT.

-- T1                                  | -- T2
BEGIN;                                 | BEGIN;
UPDATE accounts SET balance=balance-10  | UPDATE accounts SET balance=balance-10
  WHERE id=1;  -- locks row 1          |   WHERE id=2;  -- locks row 2
UPDATE accounts SET balance=balance+10  | UPDATE accounts SET balance=balance+10
  WHERE id=2;  -- waits for T2         |   WHERE id=1;  -- waits for T1 -> CYCLE
-- one transaction is chosen as victim and rolled back

Предотвращение взаимных блокировок

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

  • Единый порядок блокировок: всегда блокируйте строки в одном и том же порядке, например по возрастанию идентификатора. Это разрывает цикл.
  • Короткие транзакции: удерживайте блокировки как можно меньше времени.
  • Понижайте уровень изоляции, когда это безопасно: меньше блокировок — меньше конфликтов.
  • Добавляйте логику повторных попыток: транзакции-жертвы должны автоматически повторять попытку.

Единый порядок блокировок — самая эффективная мера и первое, что интервьюеры хотят услышать.

Детализация блокировок

Блокировки можно устанавливать на разных уровнях охвата — это компромисс между параллелизмом и накладными расходами:

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

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

MVCC: подход со снимками

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

Главное преимущество и любимая формулировка на собеседованиях: читатели не блокируют писателей, а писатели не блокируют читателей.

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

Как работает MVCC изнутри

При обновлении строки MVCC записывает новую версию и сохраняет старую. Каждая версия содержит метаданные с идентификаторами транзакций (в Postgres — xmin и xmax), указывающие, когда она стала видимой и когда была заменена.

Снимок транзакции определяет, какую версию она видит. Старые версии, которые уже не может видеть ни одна транзакция, становятся мёртвыми кортежами, а позднее освобождаются в процессе очистки. В Postgres этим занимается VACUUM; если его не запускать, возникает раздувание таблиц — частый дополнительный вопрос.

Блокировки и MVCC: компромисс

Кратко сформулируем сравнение:

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

Даже движки с MVCC используют блокировки при записи: две транзакции, обновляющие одну и ту же строку, должны выполняться последовательно. MVCC устраняет конкуренцию между читателями и писателями, но не между двумя писателями.

Оптимистические блокировки и столбцы версий

Помимо MVCC на уровне движка, приложения часто добавляют оптимистические блокировки для операций «прочитать — изменить — записать», выполняемых в течение долгих пользовательских сеансов. Вы добавляете столбец version, считываете его, а при обновлении требуете совпадения версии и увеличиваете её.

Если другая транзакция первой обновила строку, версии больше не совпадают, затрагивается ноль строк, и Ваш код понимает, что нужно загрузить данные заново и повторить попытку. Пока пользователь обдумывает изменения, блокировки не удерживаются, поэтому параллелизм остаётся высоким. Интервьюерам нравится этот подход для вопроса «как Вы обрабатываете ситуацию, когда два пользователя редактируют одну и ту же запись?».

-- read: SELECT id, data, version FROM items WHERE id = 1;  -- version = 7
UPDATE items
  SET data = 'new value', version = version + 1
  WHERE id = 1 AND version = 7;
-- if rows affected = 0, someone else changed it: reload and retry

Быстрая проверка

Проверьте ключевую формулировку о MVCC.

Итоги: блокировки, взаимные блокировки и MVCC

Теперь Вы можете объяснить механизмы, лежащие в основе изоляции:

  • Разделяемые и эксклюзивные блокировки координируют доступ; SELECT FOR UPDATE устанавливает явные блокировки записи.
  • Взаимные блокировки представляют собой циклы блокировок; движок прерывает транзакцию-жертву, а единый порядок блокировок предотвращает большинство таких ситуаций.
  • MVCC хранит версии строк, поэтому читатели и писатели не блокируют друг друга, но требует очистки (VACUUM, раздувание таблиц).

Свяжите эти механизмы с уровнями изоляции и аномалиями из предыдущих уроков — и сможете уверенно отвечать на вопросы о конкурентном доступе на собеседовании от начала до конца.

Можно начать бесплатно

Изучай Coding Interview Prep с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
90
Уроки
360

Часто задаваемые вопросы

Урок «Взаимные блокировки, блокировки и MVCC» бесплатный?

Да — полный текст урока «Взаимные блокировки, блокировки и MVCC» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Coding Interview Prep, подпишись на CoddyKit PRO. Курс Coding Interview Prep содержит 4 уроков всего.

Чему я научусь в уроке «Взаимные блокировки, блокировки и MVCC»?

Как базы данных предотвращают конфликты и чем отличаются блокировки от снимков Ты практикуешь Coding Interview Prep с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Coding Interview Prep?

Предыдущий опыт не требуется. Coding Interview Prep на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Взаимные блокировки, блокировки и MVCC»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Coding Interview Prep?

Да. Каждый урок Coding Interview Prep включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Объяснение свойств ACID
  2. Четыре уровня изоляции
  3. Грязное, неповторяемое и фантомное чтение
  4. Взаимные блокировки, блокировки и MVCC
← Назад к Coding Interview Prep