Количество слов в статье: 5889 слов. Чтение занимает около 20 минут.
В современных средах баз данных с высокой степенью параллелизма решающее значение имеет эффективный контроль параллелизма. MVCC — это широко используемый механизм управления параллелизмом в MySQL. Он обеспечивает изоляцию транзакций посредством управления версиями, позволяет одновременно выполнять операции чтения и записи, а также повышает производительность параллелизма и скорость реагирования базы данных.
В этой статье будет представлен углубленный анализ принципов механизма MVCC, чтобы помочь читателям лучше понять и применить эту ключевую технологию.
MVCC, полное название Multi-Version Concurrency Control, то есть многоверсионный контроль параллелизма.
Основная цель MVCC — повысить производительность параллельного доступа к базе данных и использовать лучший способ обработки конфликтов чтения и записи, чтобы даже в случае возникновения конфликтов чтения и записи блокировка не могла быть достигнута.
Под мультиверсией здесь понимается одновременное существование нескольких версий данных в базе данных, причем не нескольких версий всей базы данных, а нескольких версий определенной записи.
Проблемы управления параллелизмом
В системе баз данных транзакции, выполняемые одновременно, могут включать одни и те же данные, поэтому необходим механизм, обеспечивающий согласованность данных. Традиционный механизм блокировки может обеспечить управление параллелизмом, но это приведет к таким проблемам, как блокировка и взаимоблокировка.
Преимущества MVCC
Механизм MVCC имеет следующие преимущества:
Прежде чем объяснять принцип MVCC,Давайте сначала поймем,Текущее чтение и чтение снимка。
сейчас читаю
В MySQL сейчас Чтение — это метод операции чтения данных. Он может напрямую читать последнюю изданную версию. При чтении он также должен гарантировать, что другие одновременно дела не смогут изменить текущую запись, и прочитанная запись будет заблокирована. MySQL сейчас предоставляет две реализации чтениеиз Механизм:
Ниже перечислены все эти грамматики, которые сейчас читаю:
грамматика |
---|
SELECT ... LOCK IN SHARE MODE |
SELECT ... FOR UPDATE |
UPDATE |
DELETE |
INSERT |
Сейчас читаю на самом деле операция блокировки, которая представляет собой пессимистическую реализацию блокировки.
чтение снимка
чтение снимка — это единообразный вид при чтении данных, MySQL использует MVCC Механизм поддержки чтения снимка。
В частности, каждая транзакция вначале создает согласованное представление (Consistent View), которое отражает снимок базы данных в начале транзакции. Это представление согласованности записывает версию данных, которая была зафиксирована в начале текущей транзакции.
При выполнении операции запроса MySQL определяет видимую версию данных на основе согласованного представления транзакции. Видны только те версии данных, которые были зафиксированы до начала транзакции. Незафиксированные данные или данные, измененные после начала транзакции, не видны для текущей транзакции.
вроде разблокировано select Операция чтения снимка, то есть неблокирующее и неблокирующее чтение.
При чтении снимка можно прочитать, что это не обязательно последняя версия данных, а может быть предыдущая из исторической версии.
Уведомление:чтение снимкаиз Предпосылка такова, что уровень изоляции не является серийным уровнем. На серийном уровне дела выполняются полностью серийно, чтение. снимкадеградируетдлясейчас читаю
MVCC в основном реализует конфликты чтения и записи без блокировки.,И это чтение означает чтение снимка, является реализацией оптимистической блокировки.
В дополнение к полям, которые мы видим невооруженным глазом, данные строк в MySQL на самом деле также содержат некоторые скрытые поля, которые используются внутри и не будут отображаться пользователям по умолчанию.
Поле | значение |
---|---|
DB_ROW_ID | Неявный идентификатор автоматического приращения (скрытый первичный ключ) используется для уникальной идентификации каждой строки данных в таблице. Если таблица данных не имеет первичного ключа, InnoDB автоматически сгенерирует кластерный индекс с DB_ROW_ID. |
DB_TRX_ID | Поле хранит идентификатор изделия, которому принадлежат данные текущей строки. Каждое дело в библиотеке данных имеет уникальный идентификатор изделия. действовать DB_TRX_ID Поле, вы можете отслеживать строку данныхиделаиз принадлежности. |
DB_ROLL_PTR | Должен Поле Сохраненный указатель отката(Roll Указатель), который указывает на запись журнала отмены, использованную для отката транзакции. |
Журнал отмены был упомянут выше. Этот журнал отмены является ядром MVCC.
Журнал отмены (Undo Log) — это важный журнал транзакций в MySQL. Роль журнала отмены в основном имеет два аспекта:
В механизме хранения InnoDB журналы отмены делятся на два типа: вставка (вставка) журнала отмены и обновление (обновление) журнала отмены.
Примечание. Поскольку операция запроса (SELECT) не изменяет никакие записи, нет необходимости записывать соответствующий журнал отмены при выполнении операции запроса.
Изменения одной и той же строки записи различными транзакциями или одной и той же транзакцией приведут к тому, что журнал отмены строки записи станет связанным списком. Голова цепочки — это самая последняя запись, а хвост цепочки — самая старая старая запись.
Например, если транзакция А вставляет новую запись: вставьте в значения пользователя (идентификатор, имя) (1, «Сяо Мин»)
Теперь пришла транзакция B и изменила имя записи на «Сяо Ван».
Когда транзакция B изменяет данные строки, база данных сначала добавит к строке монопольную блокировку, а затем скопирует данные строки в журнал отмены как старую запись, то есть в строке отмены будет копия текущей строки. бревно.
После завершения копирования измените имя строки на «Сяо Ван, и измените скрытый ПолеизделаID для текущей Транзакции». БизID, и скопируйте указатель отката в undo log Запись копирования означает, что это моя последняя версия. После фиксации транзакции блокировка снимается.
В это время приходит другая транзакция C, чтобы изменить ту же запись и изменить имя на «Сяохун».
Когда транзакция C изменяет данные строки, база данных также сначала блокирует строку, а затем копирует данные строки в журнал отмены как старую запись. Если обнаруживается, что запись строки уже имеет журнал отмены, то используются самые последние старые данные. используется как связанный список. Заголовок вставляется в начало журнала отмены, записанного в этой строке, как показано ниже:
Что касается взаимодействия между DB_ROLL_PTR и журналом отмены, конкретный процесс выглядит следующим образом:
Например, если вы хотите вернуться к транзакции B и значением имени является «Xiao Wang», вам нужно всего лишь использовать DB_ROLL_PTR, чтобы найти соответствующий журнал отмены в списке и восстановить старое значение в строке данных.
Благодаря сотрудничеству DB_ROLL_PTR и журнала отмены MySQL может эффективно управлять согласованностью и изоляцией транзакций. Использование журналов отмены также позволяет MySQL поддерживать MVCC, тем самым обеспечивая согласованность чтения и изоляцию транзакций в средах с высоким уровнем параллелизма.
В MVCC,Для каждой операции обновления,Старая цена будет сохранена в папке отмены.,Даже если это старая версия этой записи. По мере увеличения количества обновлений,Все версии иметьиз будут иметь атрибутroll_pointer, подключенный в связанный список.,позвони этодляцепочка версий。
цепочка версиииз Головной узел представляет текущую запись и последнюю оценку. Кроме того, каждая версия также содержит идентификатор, созданный для этой версии.
Просмотр согласованности, полное имя Read View , используется для оценки цепочки версийв Какая версия правильная?когдавпередделадавидимыйиз
Read View Грубо говоря, дела осуществляет чтение снимка генерирует режим чтения (Read Просмотр), в котором читается исполнение дел снимкаизтот момент,Будет создан снимок текущей системы библиотеки данных.,Записывать и поддерживать текущий активный идентификатор делаиз системы (при включении каждого дела),будет присвоен идентификатор,Этот идентификатор увеличивается из).
здесьиметь Немного Уведомлениеодин раз:Read Просмотр только для RC и уровень RR
Read Uncommitted(RU)и Сериализуемые — это два специальных уровня изоляции, которые не нужно использовать. Read View Основные причины:
Read Uncommitted и Serializable Правила транзакций на уровне изоляции не предполагают Read View оценка видимости. РУ Допускаются грязные чтения, в то время как Serializable Механизм блокировки используется для обеспечения последовательного выполнения. Следовательно, при этих двух уровнях изоляции нет необходимости создавать или использовать Read View。
Просмотр чтения следует принципу видимости: извлекается DB_TRX_ID данных, подлежащих изменению, и сравнивается с идентификаторами других активных транзакций в системе.
Если DB_TRX_ID сравнивается со свойствами представления чтения и не соответствует видимости, используйте указатель отката DB_ROLL_PTR, чтобы получить DB_TRX_ID в журнале отмены и снова сравнить.
То есть пройти по DB_TRX_ID связанного списка (от начала цепочки до конца цепочки, то есть начиная с самой последней модификации) до тех пор, пока не будет найден DB_TRX_ID, соответствующий определенным условиям. Затем будет найдена запись, в которой этот DB_TRX_ID. находится последняя старая версия, которую может видеть текущая транзакция.
В режиме чтения будут сохранены следующие элементы:
Поле | значение |
---|---|
m_ids | Read View Другие незафиксированные активные транзакции на момент создания ID список. создавать Read Просмотр текущей незафиксированной транзакции ID Записанные, даже если они позже изменят значение строки записи, они не будут видны текущей транзакции. m_ids Не включает в себя текущие дела и уже совершенные и здела (в памяти). |
m_creator_trx_id | Идентификатор транзакции, создавшей это представление чтения. |
m_low_limit_id | Самый большой идентификатор транзакции, которая произошла на данный момент + 1, который является идентификатором следующей транзакции, которая будет назначена. Версии данных, превышающие или равные этому идентификатору, не отображаются. |
m_up_limit_id | Наименьший идентификатор транзакции в списке активных транзакций m_ids. Если m_ids пусто, m_low_limit_id равен m_up_limit_id. Версии данных, меньшие, чем этот идентификатор, видны. |
Конкретная оценка видимости в режиме чтения заключается в следующем:
DB_TRX_ID
свойствоценитьи Read View в m_creator_trx_id
ценитьтакой же,Указывает, что дела в настоящее время обращается к записи, которую он изменил.,Поэтому эта версия может быть доступна текущим делам.DB_TRX_ID
Атрибут ценить меньше чем Read View в m_up_limit_id
ценить, указывая, что данная версия сгенерирована в текущих делах Read View Уже отправлено ранее,Поэтому эта версия может быть доступна текущим делам.DB_TRX_ID
Атрибут ценить больше или равен Read View в m_low_limit_id
ценить, указывая, что данная версия сгенерирована в текущих делах Read View Оно будет зафиксировано позже, поэтому текущие дела не смогут получить доступ к этой версии.DB_TRX_ID
Объект ценить находится в Read View из m_up_limit_id
и m_low_limit_id
между (включая границы), требуется дальнейшая проверка DB_TRX_ID
да Ты здесь?m_ids
в списке. если есть в списке, что указывает на то, что версия была сгенерирована при создании ReadView, все еще активна, поэтому доступ к этой версии невозможен; если ее нет в списке, это указывает на то, что версия была сгенерирована при создании ReadView. Read View Когда эта версия создается, издела уже зафиксировано, поэтому к этой версии можно получить доступ.Схема видимости транзакции:
RC и RR созданный под Read View
Время другое:
Только из-за RC и Генерация RR Read View Сроки различаются, что приводит к противоречивым данным на двух уровнях.
Например, предположим, что исходное состояние данных следующее:
Имеется три транзакции A, B и C. Порядок выполнения следующий:
Транзакция А (идентификатор транзакции: 100) | Транзакция Б (идентификатор транзакции: 200) | Транзакция C (идентификатор транзакции: 300) | |
---|---|---|---|
T1 | begin | ||
T2 | begin | begin | |
T3 | обновить имя набора пользователей = "Сяо Ван", где id = 1 | ||
T4 | обновить имя набора пользователей="Маленький красный", где id=1 | select * from user where id = 1 | |
T5 | commit | обновить имя набора пользователей="Сяохэй", где id=1 | |
T6 | обновить имя набора пользователей = "Xiaobai", где id = 1 | select * from user where id = 1 | |
T7 | commit | ||
T8 | select * from user where id = 1 | ||
T9 | commit | ||
T10 |
Момент Т4
Давайте посмотрим T4 моментальная ситуация, в это время Транзакция А и Транзакция Б Ни одна из них еще не была отправлена, поэтому идентификатор активной транзакции: m_ids
для: [100, 200] четыре Полеизценить следующие:
Поле | ценить |
---|---|
m_ids | [100,200] |
m_creator_trx_id | 300 |
m_low_limit_id | 400 |
m_up_limit_id | 100 |
Момент Т4изцепочка версийследующее:
Согласно принципу видимости, о котором мы упоминали ранее, то, что в конечном итоге увидит транзакция C, должно быть name = «Сяо Мин»
данные по следующим причинам:
последняя запись DB_TRX_ID
для 100, не менее m_up_limit_id
,и не больше, чем m_low_limit_id
,И оно не равно m_creator_trx_id
。
Попадание в желтую зону:
DB_TRX_ID
существовать в m_ids
в списке, чтобы его не было видно, следите за цепочкой версия продолжает опускаться.
в соответствии с DB_ROLL_PTR
оказаться undo log
Предыдущая запись версии в , предыдущая запись DB_TRX_ID
все еще 100,все еще Нетвидимый,Продолжайте спускаться.
Продолжить поиск предыдущего элемента DB_TRX_ID
для 1. Удовлетворить 1 < m_up_limit_id
,видимый,SoC Найденныйданныедля name = «Сяо Мин»
。
Т6 момент
На Т6 исход изцепочки выглядит следующим образом:
Т6 момент, снова сгенерирует новое Read View,Четыре Полеизценения заключаются в следующем:
Поле | ценить |
---|---|
m_ids | [200] |
m_creator_trx_id | 300 |
m_low_limit_id | 400 |
m_up_limit_id | 200 |
в соответствии спринцип видимости,Финал Т6 моментделаC Найденныйданныедля name = "Маленький красный"
。
Т8 момент
Т8 моментизцепочка версийи Т6 момент соответствует из, отличается от Read Посмотреть, автордля Т8 момент переродится в другой Read View,Четыре Полеизценения заключаются в следующем:
Поле | ценить |
---|---|
m_ids | [] |
m_creator_trx_id | 300 |
m_low_limit_id | 400 |
m_up_limit_id | 400 |
в соответствии спринцип видимости,финальный Т8 моментделаC Найденныйданныедля name = "нуб"
。
Подвести итог,делаC здесь RC Данные, видимые в каждый момент под уровнем, следующие:
время | name |
---|---|
T4 | Сяо Мин |
T6 | Сяохун |
T8 | нуб |
под Давайте посмотримсмотреть,RR Как он работает на разных уровнях?
(RR изцепочка версийи RC изцепочка путь такой же, как и из, разница в том, что Read View)
Момент Т4
T4 времяиз ситуации,и R Ситуация в C последовательная:
Поле | ценить |
---|---|
m_ids | [100,200] |
m_creator_trx_id | 300 |
m_low_limit_id | 400 |
m_up_limit_id | 100 |
в соответствии спринцип видимости,финальный Момент Т4делаC Найденныйданныедля name = «Сяо Мин»
,и RC из Момент Т4 соответствует из.
Т6 момент
RR Уровни будут использоваться повторно Read Посмотреть, итак Т6 моменттакжеда:
Поле | ценить |
---|---|
m_ids | [100,200] |
m_creator_trx_id | 300 |
m_low_limit_id | 400 |
m_up_limit_id | 100 |
в соответствии спринцип видимости,Т6 моментмы нашлиделаCquery to изданныевсе еще name = «Сяо Мин»
。
Продолжить просмотр Т8 момент.
Т8 момент
Т8 моментпродолжить повторно использовать предыдущее из Read View。
в соответствии спринцип видимости,Т8 моментаделаC обнаружила, что изданные все еще name = «Сяо Мин»
。
Мы помещаем транзакцию C в RC и RR Данные, видимые под уровнем, объединены для сравнения:
время | RC | RR |
---|---|---|
T4 | Сяо Мин | Сяо Мин |
T6 | Сяохун | Сяо Мин |
T8 | нуб | Сяо Мин |
Видно, что оба они генерируют Прочитать Просмотр из Время разное, что приводит к различиям в просмотре изданных в каждое время.
Оглядываясь назад RC и RR Определение уровня изоляции даст вам ощущение просветления:
Во всяком случае, здесь RC При уровне изоляции каждое чтение снимка сгенерирует и получит последние новости Read Посмотреть, находясь в RR На уровне изоляции это только при первом прочтении фото создано Читать Посмотреть, после прочтения снимкаgetиз все одинаковые Читать View
Строго говоря, уровень RR может предотвратить только частичное фантомное чтение.
Прежде всего, фантомное чтение обычно означает, что в той же транзакции второй запрос находит вновь добавленные строки, но первый запрос эти вновь добавленные строки не возвращает.
В предыдущем примере мы также увидели, что на уровне изоляции RR из-за существования согласованных представлений, если другие транзакции вставляют новые строки и в одной транзакции выполняется несколько запросов, эти новые строки будут включены в представление согласованности. транзакций, некоторых сценариев фантомного чтения действительно можно избежать.
Обратите внимание: MVCC решает только RR Понижение уровня проблема с фантомным чтением, и сейчас Проблема чтения с фантомным чтением решается с помощью Pro Key Lock. То есть RR уровень пройден MVCC+про ключевой замок Чтобы решить большинство проблем с фантомным чтением.
Что вы подразумеваете под частичным решением? Рассмотрим следующий пример:
Транзакция А | Транзакция Б | |
---|---|---|
T1 | begin | |
T2 | begin | |
T3 | select * from user | |
T4 | вставить в значения пользователя(id, name)(2, "Сяо Чжан") | |
T5 | select * from user for update | |
T6 | commit | |
T7 | commit |
Предположим, что исходное состояние данных следующее:
Т3время пилы изданные только есть name = «Сяо Мин»
,И Т5время,потому что select * from user for update Использовать из сейчас читаю, читаю из — последняя версия изданных, Т5время обнаруживает, что изданные — это два слова, имя соответственно для «Сяо Мин» и «Сяо Чжан».
Поняв приведенный выше пример, посмотрите на следующий пример:
Транзакция А | Транзакция Б | |
---|---|---|
T1 | begin | |
T2 | begin | |
T3 | select * from user | |
T4 | вставить в значения пользователя(id, name)(2, "Сяо Чжан") | |
T5 | обновить имя набора пользователей = "Сяо Чен", где id = 2 | |
T6 | select * from user | |
T7 | commit | |
T8 | commit |
UPDATE Приговор также сейчас читаю, также возникнут фантомные проблемы с чтением, и, наконец, мы видим, что «изданные» — это имя соответственно для «Сяо Мин» и «Сяо Чен».
Причина, по которой происходит фантомное чтение, здесь,Приведенный выше пример аналогичен,Суть все в одном деле,Прямо сейчасиспользовать Понятночтение снимок снова использован сейчас читаю,RR Эту ситуацию невозможно предотвратить на этом уровне, поэтому RR Проблема фантомного чтения не может быть полностью решена на этом уровне.
Подводя итог, MVCC Это мощный механизм управления параллелизмом, который играет важную роль в средах с высоким уровнем параллелизма. понимая MVCC из Принципа и процесса реализации мы можем лучше понять MySQL Механизм управления параллелизмом, понимание MVCC Принцип контакта MySQL Это важная точка знаний для разработчиков.
Я надеюсь, что эта статья будет полезна всем студентам и углубит их понимание MVCC и его применения в MySQL. Если эта статья вам полезна, поставьте ей лайк 👍🏻 или прочитайте ее еще раз. Спасибо за чтение!
Нажмите здесь, чтобы увидеть больше.
·················END·················