Раздел 10 · Databases

Блокировки, сериализуемость и восстановление

junior~15 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

В прошлом уроке транзакции то ждали друг друга, то откатывались с ошибкой. Этот урок заглядывает под капот. Сначала разберём, что значит «правильное» одновременное выполнение, потом блокировки, которые его обеспечивают, и взаимное ожидание, в которое они могут завести. В конце посмотрим, как база выполняет обещание долговечности: журнал и восстановление после сбоя.

Правильный порядок

Две транзакции идут одновременно, их команды перемешаны. Как понять, что результат правильный? Ориентир такой: результат должен совпасть с одним из вариантов, где транзакции шли бы по одной, сначала T1 целиком, потом T2, или наоборот.

Это свойство называют сериализуемостью. Потерянное обновление из прошлого урока ей не соответствует: при любом последовательном порядке у Пети списалось бы 8000, а не 3000. Уровень Serializable обещает ровно это свойство.

Блокировки

Аналогия: библиотечная книга. Читать её в читальном зале могут несколько человек одновременно. Но если кто-то взял книгу, чтобы вписывать исправления, остальным придётся подождать, пока он не вернёт её.

Блокировка устроена так же. Их два основных вида:

  • разделяемая (S), для чтения: несколько транзакций держат её на одной строке одновременно;
  • исключительная (X), для записи: пока её держит одна транзакция, остальные ждут.
держат Sдержат X
просят Sможнождать
просят Xждатьждать

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

Двухфазная блокировка

Одних блокировок мало: важно, когда их снимать. Если отпустить строку слишком рано, другая транзакция успеет вклиниться, и сериализуемость пропадёт.

Правило, которое её гарантирует, называют двухфазной блокировкой, 2PL:

  1. Фаза роста. Транзакция только захватывает блокировки, ничего не отпуская.
  2. Фаза сжатия. После первой отпущенной блокировки новые захватывать нельзя.

На практике используют строгий вариант: исключительные блокировки держатся до самого COMMIT или ROLLBACK. Так другие транзакции никогда не видят и не перезаписывают незафиксированные изменения.

дальше после входа

Урок целиком открыт всем, кто вошёл. Войди по своему email, чтобы читать дальше.

Вход пока по приглашению. Если хочешь учиться, напиши Vassiliy.