Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность.
Ранее мы представили механизм хранения InnoDB на уровне изоляции транзакций.READ COMMITTED и REPEATABLE READСогласованное чтение без блокировки будет включено по умолчанию. Давайте кратко рассмотрим: Так называемое последовательное чтение без блокировки означает, что может быть несколько исторических версий каждой строки записей, и несколько версий соединены последовательно, чтобы сформировать версию. цепочки, чтобы разные версии запускались в разное время.нет замкадоступ к различным версиям данных.
цепочка версий журнала отмены
Согласованное неблокирующее чтение выполняется черезMVCC (управление параллелизмом нескольких версий)быть реализованным. На самом деле MVCC не имеет единого стандарта реализации, поэтому механизм реализации каждого механизма хранения отличается.
Реализация MVCC в механизме хранения InnoDB осуществляется черезundo logЧтобы завершить, что такое журнал отмены?
просто понять,журнал отмены - это обратная операция каждой операцииНапример, если текущая транзакция выполняет операцию вставки записи с id = 100, то в журнале отмены сохраняется операция удаления записи с id = 100.
Поэтому не очень точно описывать здесь несколько версий, потому что InnoDB на самом деле не освобождает место для хранения нескольких версий записей строк, а только использует журнал отмен для записи обратной операции каждой операции записи.
То есть соответствующая запись в индексном дереве B+ будет иметь только самую последнюю версию, но InnoDB можетПолучить историческую версию данных согласно журналу отмен, чтобы обеспечить управление несколькими версиями.
Тогда возникает еще один вопрос: как журнал отмены связан с записью строки? Другими словами, как я могу найти журнал отмен по этой строчной записи?
Конкретно,Каждая запись строки в механизме хранения InnoDB фактически имеет два скрытых поля:trx_id
иroll_pointer
.
Как видно из названия,trx_id
это идентификатор транзакции, которая последний раз обновляла эту запись строки,roll_pointer
Он указывает на ранее сгенерированный журнал отмены.
Возьмите нашу пользовательскую таблицу, например, предположим, что транзакция A с идентификатором = 100 вставляет запись строки (id = 1, имя пользователя = «Джек», возраст = 18), затем два скрытых поля этой записи строкиtrx_id = 100
иroll_pointer
Указывает на пустой журнал отмены, потому что нет предыдущей записи операции транзакции с идентификатором = 1. как показано на рисунке:
Затем транзакция B с id = 200 изменяет запись строки, изменяя возраст с 18 до 20 лет, поэтому запись строкиtrx_id
становится 200,rooll_pointer
Он указывает на журнал отмены, сгенерированный транзакцией A:
Затем транзакция C с id = 300 снова изменила запись строки, изменив возраст с 20 на 30, как показано ниже:
Видно, что два скрытых поля trx_id и roll_pointer обновляются каждый раз при изменении записи строки.Журналы отмены, соответствующие предыдущим множественным снимкам данных, будут объединены с помощью указателя roll_pointer для формированияцепочка версий.
должны знать о том,операция выбора запроса не будет генерировать журнал отмены! В механизме хранения InnoDB есть только два типа журналов отмены:
- вставить журнал отмены: журнал отмены, сгенерированный во время операции вставки.
- обновить журнал отмены: журнал отмены, созданный операциями удаления и обновления.
На самом деле, из-за требования изоляции транзакций запись операции вставки видна только самой транзакции, но не другим транзакциям, так что в случае параллелизма проблем не возникает. Итак, то естьМеханизм MVCC фактически реализуется журналом отмены обновлений., в основном не имеет ничего общего с вставкой журнала отмены.Цепочка версий журнала отмены, о которой мы упоминали выше, на самом деле является журналом отмены обновления.
Механизм чтения
Когда дело доходит до MVCC и цепочки версий журнала отмены, если вы сами не расскажете об этом, интервьюер спросит вас о механизме ReadView.
Мы не продаем чиновников, скажем прямо,Механизм ReadView используется для определения того, какие версии может видеть текущая транзакция., ReadView в основном включает следующие части:
-
m_ids
: какие транзакции были выполнены, но еще не зафиксированы, когда был сгенерирован ReadView (называется «активная транзакция"), идентификаторы этих активных транзакций хранятся в этом поле. -
min_trx_id
: наименьшее значение в m_ids -
max_trx_id
: значение идентификатора, который InnoDB назначит следующей транзакции при создании ReadView (идентификатор транзакции назначается постепенно, и чем позже применяется идентификатор транзакции). -
creator_trx_id
: идентификатор текущей созданной транзакции ReadView.
Затем выньте таблицу пользователей и используйте пример, чтобы понять, как механизм ReaView определяет, какие версии может видеть текущая транзакция:
Предположим, запись строки (id = 1, username = "Jack", age = 18) была вставлена в таблицу предыдущей транзакцией A (id = 100), как показано на рисунке:
Далее приходят две транзакции B (id = 200) и C (id = 300).параллельное выполнение, транзакция B хочет обновить (обновить) запись с id = 1, а транзакция C (выбрать) хочет запросить эту строку данных, обе транзакции выполнили соответствующие операции, но еще не совершили коммит:
Если транзакция B теперь открывает ReadView, в этом ReadView:
-
m_ids
Он содержит идентификатор текущей активной транзакции, то есть два идентификатора транзакции B и транзакции C, 200 и 300. -
min_trx_id
200 -
max_trx_id
это идентификатор следующей транзакции, которая может быть выделена, то есть 301 -
creator_trx_id
это идентификатор 200 текущей созданной транзакции ReadView B
Теперь транзакция B выполняет первый запрос (как упоминалось выше, операция выбора не будет генерировать журнал отмены), онаПоместите скрытое поле этой строки записейtrx_id
и ReadViewmin_trx_id
вынести суждение, на данный момент установлено, что trx_id равен 100, что меньше, чем в ReadViewmin_trx_id
(200), что означает, что до начала транзакции B транзакция A, изменяющая эту строку записей, уже зафиксирована, поэтомуТранзакция B, которая начинается после фиксации транзакции A, может узнать об обновлении транзакции A в этой строке записей..
row.trx_id < ReadView.min_trx_id
Затем пришла транзакция C, чтобы изменить эту строку записей и изменить age = 18 на age = 20, так что эта строка записейtrx_id
становится 300, аroll_pointer
Указывает на журнал отмены, созданный до изменения транзакции C:
В это время, когда транзакция B снова выполнит операцию запроса, она обнаружит, чтоэта строка записываетtrx_id
(300) больше, чем у ReadViewmin_trx_id
(200), и менееmax_trx_id
(301).
row.trx_id > ReadView.min_trx_id && row.trx_id < max_trx_id
Это указывает на проблему, то есть транзакция, которая обновляет эту строку записей, вероятно, также существует в m_ids (активных транзакциях) ReadView. Таким образом, транзакция B будет судить о наличии m_ids в ReadView.trx_id = 300
Транзакция с id = 300, очевидно, существует, а это значит, что транзакция с id = 300 является транзакцией, выполняемой одновременно с самой собой (транзакция B) в тот же период времени, а это значит, что запись транзакции B с возрастом = 20 не может быть запрошена. .
Поскольку это не может быть запрошено, что мне делать? Что может найти транзакция B в этой операции запроса?
Верно, цепочка версий журнала отмен!
В это время транзакция B будет искать указатель roll_pointer, записанный в этой строке, и найдет самый последний.trx_id = 100
журнал отмены, а его собственный идентификатор равен 200, что означает, что версия журнала отмены с trx_id = 100 должна быть отправлена до открытия транзакции B. Следовательно, операция запроса транзакции B считывает эту версию данных, а именно age = 18.
Из вышеприведенного примера мы можем сделать вывод, что,Благодаря цепочке версий журнала отмены и механизму ReadView можно гарантировать, что одна транзакция не будет читать обновления другой параллельно выполняемой транзакции..
Могу ли я прочитать значение, которое я изменил самостоятельно?
Это ерунда, конечно, и читать точно можно. Но в приведенном выше примере мы рассмотрели только первые три поля в ReadView, аcreator_trx_id
Это связано с чтением собственных модификаций, поэтому вот схема, чтобы все могли лучше понять механизм ReadView:
Предположим, модификация транзакции C была зафиксирована, а затем транзакция B обновляет запись строки, изменяя age = 20 на age = 66, как показано на следующем рисунке:
Затем транзакция B снова запрашивает эту запись и находит, чтоtrx_id = 200
с ReadView вcreator_trx_id = 200
То же самое, это означает, что это то, что я только что изменил, и, конечно, это может быть запрошено.
row.trx_id = ReadView.creator_trx_id
Тогда если во время выполнения транзакции B вдруг откроется транзакция D с id=400, а затем будет обновлен и отправлен age=88 этой строки записей, а затем транзакция B пойдет читать эту строку записей, может ли она читать?
Ответ - нет.
Потому что в это время, когда транзакция B запрашивает эту строку записей, она находитtrx_id = 500
больше, чем в ReadViewmax_trx_id = 301
, что означает, что во время выполнения транзакции B другая транзакция обновила данные, поэтому нельзя запросить обновление другой транзакции.
row.trx_id > ReadView.max_trx_id
Из вышеприведенного примера мы можем сделать вывод, что,Благодаря цепочке версий журнала отмены и механизму ReadView можно гарантировать, что транзакция может считывать только данные, измененные самой транзакцией, или данные до начала транзакции..
резюме
Подводя итог, через цепочку версий журнала отмены и механизм ReadView:
- Гарантируется, что одна транзакция не будет читать обновления из другой параллельно выполняющейся транзакции.
- Можно гарантировать, что транзакция может считывать только данные, измененные самой транзакцией, или данные до начала транзакции.
Кроме того, как упоминалось ранее, последовательное неблокирующее чтение (или MVCC, в конце концов, согласованное неблокирующее чтение также реализуется MVCC) будет включено только на уровнях изоляции транзакций READ COMMITTED и REPEATABLE READ (по умолчанию), то есть для На самом деле, самое фундаментальное различие между этими двумя уровнями изоляции заключается в том, что ониВремя создания ReadView отличается, это мы объясним ниже ~
🎉 Подпишитесь на официальный аккаунт | Feitian телятина, получайте мгновенные обновления
-
Блогер учится в магистратуре Юго-восточного университета и проходит летнюю стажировку в Ctrip, занимаясь фоновой разработкой Java.Публичный аккаунт "Летучая телятина", открытый 29 декабря 2020 г., с акцентом на обмен основами работы с компьютером (структура данных + алгоритм + компьютерная сеть + база данных + операционная система + Linux), технологический стек Java и другие полезные оригинальные технические статьи. Обратите внимание на официальный аккаунт, чтобы получать обновления статьи как можно скорее,
后台回复 300 即可免费获取极客大学出品的 Java 面试 300 题
-
И порекомендуйте учебные проекты с открытым исходным кодом для личного обслуживания:CS-Wiki (рекомендовано Gitee, набрало более 1,8 тыс. звезд), Стремясь создать полную внутреннюю систему знаний и избегая окольных путей на пути технологий, приглашаем всех друзей прийти, чтобы обменяться и учиться ~ 😊
-
Если у вас, ребята, нет проекта, который вы могли бы сделать весной и осенью, вы можете обратиться к проекту, который я написал.«Система сообщества с открытым исходным кодом Echo», официально рекомендованная Gitee, набрала более 900 звезд., основанный на SpringBoot + MyBatis + MySQL + Redis + Kafka + Elasticsearch + Spring Security + ... и предоставляет подробную документацию по разработке и вспомогательные учебные пособия. Вы можете получить вспомогательные руководства, ответив на Echo в фоновом режиме официальной учетной записи, которая все еще обновляется.