Представьте сегодня, в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
заявление регенерируется. Согласно приведенному выше содержанию, вы можете прочитать и отправить его самостоятельно.