Photo by picography.co
Примечания к «MySQL Практические 45 лекций».
Простое понимание можно прочитать снова
Повторяемое чтение означает, что данные, видимые во время выполнения транзакции, всегда согласуются с данными, замеченными транзакцией при запуске.
Мы можем просто понимать это так: при уровне изоляции повторяющегося чтения транзакция «делает снимок» при запуске. Обратите внимание, что этот снимок основан на всей библиотеке.
В это время вы можете подумать, если имеет базу данных 100 г, то я запускаю транзакцию, а MySQL будет скопировать 100 г данных. Насколько медленно этот процесс. Тем не менее, мои обычные дела проводятся очень быстро.
На самом деле нам не нужно копировать данные этого 100G. Мы смотрим на "моментальный снимок", как достичь.
сделать снимок
Каждая транзакция в InnoDB имеет уникальный идентификатор транзакции, называемый идентификатором транзакции. Он применяется к системе транзакций InnoDB в начале транзакции и строго увеличивается в порядке применения.
При обновлении каждой записи одновременно будет записываться журнал отмены, и этот журнал будет записывать идентификатор транзакции текущей транзакции, который записывается как строка trx_id. Последнее значение в записи посредством операции отката может получить значение предыдущего состояния.
Как показано на рисунке ниже, после обновления строки записей несколькими транзакциями последнее значение равно k=22. Предположим, транзакция A находится в этой транзакции с trx_id=15.Начать после отправки, когда транзакция A хочет прочитать строку, она использует журнал отмены для вычисления значения строки в момент начала транзакции, k=10.
При уровне изоляции повторяющегося чтения, когда транзакция запускается, InnoDB создаст массив для транзакции для хранения всех идентификаторов транзакций, которые в настоящее время «активны» в момент запуска транзакции. «Активный» означает запущенный, но еще не зафиксированный.
Минимальный идентификатор транзакции в массиве записывается как низкий уровень воды, а максимальное значение идентификаторов транзакций, созданных в текущей системе, плюс 1 записывается как высокий уровень воды.
Этот массив просмотров и высшая отметка составляют просмотр для чтения текущей транзакции.
Этот массив представлений делит всю строку trx_id на несколько разных случаев.
- Если trx_id меньше минимального уровня воды, это означает, что эта версия была зафиксирована до начала транзакции, что видно;
- Если TRX_ID больше, чем высокая вода, это означает, что эта версия генерируется после запуска транзакции и не видна;
- Если trx_id больше, чем низкий уровень воды и меньше, чем высокий уровень воды, возможны два случая:
- Если в массиве есть trx_id, это означает, что эта версия не была зафиксирована при запуске транзакции и не видна;
- Если trx_id отсутствует в массиве, это означает, что эта версия была зафиксирована при запуске транзакции, что видно.
InnoDB - это возможность использовать журнал UNDO и TRX_ID для реализации способности запуска транзакции мгновенного «Снимок создания второго уровня».
взять каштан
оператор инициализации
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`k` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, k) values(1,1),(2,2);
Следующая таблица показывает выполнение потока транзакций A, B, C
Транзакция А | Транзакция Б | Транзакция C. |
---|---|---|
START TRANSACTION WITH CONSISTENT SNAPSHOT; | ||
START TRANSACTION WITH CONSISTENT SNAPSHOT; | ||
UPDATE t SET k=k+1 WHERE id=1; | ||
UPDATE t SET k=k+1 WHERE id=1; | ||
SELECT k FROM t WHERE id=1; | ||
SELECT k FROM t WHERE id=1; | ||
COMMIT; | ||
COMMIT; |
Предположим, что trx_id транзакций A, B и C равны 100, 101 и 102 соответственно. Идентификатор транзакции, который был активен до начала транзакции А, равен всего 99, а строка данных с id=1 имеет trx_id=90.
Согласно предположению, мы получаем массив представления на момент старта транзакции: транзакция A: [99, 100], транзакция B: [99, 100, 101], транзакция C: [99, 100, 101, 102].
- C транзакцией оператора обновления, обновленные k 2, то trx_id = 102;
- Транзакция B обновляется до 3, обновляя оператор, в это время trx_id = 101;
- С помощью оператора запроса транзакция B обнаруживает, что последней записью является 3, trx_id=101, что удовлетворяет условию изоляции, и возвращает k=3;
- Транзакция A передает оператор запроса:
- Последняя запись 3, trx_id=101, что больше, чем высокий уровень воды и невидимо;
- Через журнал отмен найдите предыдущую историческую версию, trx_id=102, которая больше, чем уровень прилива и невидима;
- Продолжайте искать историческую версию, TRX_ID = 90, меньше, чем низкий уровень воды, видимый.
Задайте вопрос: почему транзакция B обновляет время, чтобы увидеть измененное C дел?
Мы предполагаем, что транзакция B не может видеть модификацию транзакции C при ее обновлении.Какова ситуация?
- Транзакция B запрашивает, что последняя запись равна 2, trx_id=102, что больше уровня прилива и невидимо;
- Через журнал отмен найдите предыдущую версию, trx_id=90, меньше, чем низкий уровень воды, видимый;
- Вернуть запись k=1, выполнить k=k+1, обновить k до 2, в это время trx_id=101.
В этом случае транзакция С может быть ослеплена: «Что за ситуация, почему у меня пропало обновление». Транзакция B перезаписывает обновление транзакции C.
Итак, InnoDB применяет правило при обновлении:Обновленные данные читаются сначала, а затем записаны, и это чтение может прочитать только текущее значение, которое называется «текущий чтение».
Следовательно, транзакция B должна получать самые свежие данные при ее обновлении и обновлять их на этой основе. Затем, когда транзакция B читает, последняя запись равна 3, а trx_id=101 — это текущий идентификатор транзакции, который виден.
Предположим другую ситуацию:
После обновления транзакции B немедленно обновляется транзакция C, выполняется откат транзакции B и успешно фиксируется транзакция C.
Транзакция Б | Транзакция С |
---|---|
START TRANSACTION WITH CONSISTENT SNAPSHOT; | |
START TRANSACTION WITH CONSISTENT SNAPSHOT; | |
UPDATE t SET k=k+1 WHERE id=1; | |
UPDATE t SET k=k+1 WHERE id=1; | |
SELECT k FROM t WHERE id=1; | |
ROLLBACK; | |
COMMIT; |
В соответствии с определением текущего чтения происходит следующая авария, предполагая, что ток K=1:
- Транзакция B обновляет k до 2;
- Транзакция C считывает текущее последнее значение, k=2, и обновляется до 3;
- Транзакция B откатывается;
- Транзакция C фиксируется.
В это время транзакция C обнаруживает, что она хочет выполнить операцию +1, и результатом становится операция «+2».
InnoDB определенно не позволяет этому случиться.Когда транзакция B выполняет оператор обновления, она добавит блокировку строки к строке, и блокировка не будет снята до тех пор, пока транзакция B не завершится.
резюме
- InnoDB имеет несколько версий данных строки, каждая из которых имеет строку trx_id.
- Создайте согласованное представление об уровнях изоляции транзакций в соответствии с текущим журналом отмены и trx_id.
- Ядром повторяемого чтения является согласованность чтения, а транзакция обновляет данные только при текущем чтении, блокировка текущей записи, если строка занята другими делами, нужно ввести блокировку ожидания.
Ссылаться на
03 | Изоляция транзакции: почему я не вижу ее после того, как вы ее изменили? - Компьютерное время
08 | Являются ли транзакции изолированными или нет? - Компьютерное время
Эта статья была впервые опубликована в моем личном блогеchaohang.top
авторЧжан Сяочао
Публичный аккаунт [Чаочао не умеет летать]
Пожалуйста, укажите источник
Я приветствую внимание к общественному номеру микро-канала [Ultra] не будет летать, получать обновления в первый раз.
В этой статье используетсяmdniceнабор текста