Представьте сегодня, в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
В это время поиск будет выполняться по правилам запроса, а именно:
-
если данные
db_trx_id < min id, это означает, что данные были отправлены до открытия текущей транзакции, и содержимое видно. -
если данные
db_trx_id > max id, это означает, что данные генерируются после запуска транзакции, и содержимое не видно. -
если данные
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заявление регенерируется. Согласно приведенному выше содержанию, вы можете прочитать и отправить его самостоятельно.