Принцип реализации уровня изоляции транзакций MySQL InnoDB

MySQL

Представьте сегодня, вMySQLизInnoDBВ механизме хранения, как реализована изоляция транзакций.

InnoDBКаждая транзакция внутри имеет уникальную транзакциюID, называетсяtransaction id. Он отправляется вInnoDBЗаявки на транзакционную систему строго возрастают в порядке подачи заявок.

Для каждой строки в базе данных есть три скрытых поля:db_trx_id (事务 id),db_roll_pt (回滚指针),delete_flag(删除标记). —У меня есть друзья, которые понимаютdelete_flagнаходится в шапке информация, здесь для простоты понимания

заDMLОперативно:

  • INSERT: создать часть данных,db_trx_idтекущая транзакцияid, db_roll_ptзаnull.
  • UPDATE: скопировать строку данных, скопировать текущую строку после копированияdb_trx_idустановить на текущую транзакциюid,db_roll_ptЯвляется указателем на тот, который находится перед копией.
  • DELETE: скопировать строку данных, скопировать текущую строку после копированияdb_trx_idустановить на текущую транзакциюid,db_roll_ptЯвляется указателем на тот, который находится перед копией. и положиdelete_flagустановлен вtrue.

Мы будем использовать этот оператор для создания таблиц и инициализации данных для следующих примеров:

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `k` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

insert into t(id, k) values(1, 1);

Начальное состояние данных:

Повторяемое чтение Повторяемое чтение

Если текущий класс карантинаRepeatable Read, следующий процесс выполнения SQL:

Итак, для строк 8, 10, 12, 13 каким должен быть результат запроса?

Результат должен быть: 2, 1, 3, 1 соответственно.

Давайте пошагово воспроизведем, как нижний слой MySQL реализует весь этот процесс:

  • Строка 1: указывает идентификационный номер каждой транзакции, гдеread viewПринимает массив всех текущих активных идентификаторов транзакций. Активные относятся к транзакциям, которые были открыты и сгенерированы идентификаторы транзакций, но не были зафиксированы.max idВозьмем пока самый большой идентификатор транзакции,подано или нет. мы также звонимread viewВ массиве наименьшее значение равноmin id.

  • Строки 2–4: указывает, что использование разрешено, соответственно, и транзакция создана.read viewа такжеmax id, надо отметить, что здесь я не использовалbegin/start transactionдля запуска транзакций, потому что они не создаются сразуread viewа такжеmax id, но реализация первогоselectПосле утверждения, чтобы создать.

  • 5-я строка изменяет значение k и увеличивает его на 1. Согласно приведенным выше правилам, после модификации:

  • Строка 6 фиксирует транзакцию с идентификатором 102.

  • Строка 7 выполняет простой запрос, транзакция не запускается вручную, а также автоматически запускается и генерируетсяread viewа такжеmax id, соответственноread-view: [100, 101],max-id: 103

В это время поиск будет выполняться по правилам запроса, а именно:

  1. если данныеdb_trx_id < min id, это означает, что данные были отправлены до открытия текущей транзакции, и содержимое видно.

  2. если данныеdb_trx_id > max id, это означает, что данные генерируются после запуска транзакции, и содержимое не видно.

  3. если данныеmin id <= db_trx_id <= max id, то возможны два случая:

    3.1 Еслиdb_trx_idсуществуетread viewВ массиве , указывающем, что эта версия сгенерирована еще не зафиксированной транзакцией, она не видна, но если это собственная транзакция, то видна.

    3.2.Если его нет в данных, значит, эта версия сгенерирована транзакцией, которая была зафиксирована, что видно.

Схематическая диаграмма выглядит следующим образом:

Непротиворечивое представление текущей транзакцииread view: [100, 101],max id: 103, затем в соответствии с этим правилом запросите данные в приведенной выше цепочке данных, начните с последнего синего цвета и найдите первые данныеdb_trx_idЭто 102, и правило 3.2 относится к видимому диапазону, а результат запроса равен 2.

  • Строка 8, представление согласованности текущей транзакцииread view: [100, 101],max id: 101Также по правилам первые данныеdb_trx_idравно 102, соответствует правилу 2, не видно, то по указателюdb_roll_ptпродолжай искать, найдиdb_trx_idДанные 10 соответствуют правилу 1, данные видны, а результат запроса равен 1.

  • Строка 9, измените значение k, увеличьте его на 1, в соответствии с указанными выше правилами, после модификации:

  • Строка 10, представление согласованности текущей транзакцииread view: [100],max id: 100Также по правилам первые данныеdb_trx_idсоставляет 100, в соответствии с правилом 3.1, вread viewВ массиве, но этот идентификатор является идентификатором текущей транзакции, поэтому он виден, а результат запроса равен 3.

  • Строка 11, представление согласованности текущей транзакцииread view: [100, 101],max id: 101Также по правилам первые данныеdb_trx_idсоставляет 100, в соответствии с правилом 3.1, вread view, но этот id не является id текущей транзакции, поэтому содержимое видно, то по указателюdb_roll_ptпродолжай искать, найдиdb_trx_idДанные для 102, соответствуют правилу 2, не видны, продолжаются по указателюdb_roll_ptнайти, найтиdb_trx_idДанные 10 соответствуют правилу 1, данные видны, а результат запроса равен 1.

  • Строки 12-13, зафиксируйте оператор транзакции.

Чтение зафиксировано

вRead Committed 读已提交Приведенные выше правила также могут быть применены, но с последовательным представлением:read viewа такжеmax idсоздается во время каждогоselectзаявление регенерируется. Согласно приведенному выше содержанию, вы можете прочитать и отправить его самостоятельно.