Что такое МВЦК?
Параллельный контроль базы данных — блокировки
Multiversion (version) concurrency control (MCC or MVCC) Многоверсионный контроль параллелизма, который является обычным элементом управления параллелизмом в системах управления базами данных.
Мы знаем, что блокировки обычно используются в управлении параллелизмом.Когда поток хочет работать с общим ресурсом, блокировка — очень простой и грубый метод (добавление блокировки чтения в DQL и блокировки записи в DML в начале транзакции). .замок - этопессимистичныйТо, как он реализован, означает, что он будет блокировать другие транзакции, что повлияет на производительность базы данных.
позволь мне объяснитьоптимистическая блокировкаипессимистический замокКонцепция чего-либо.Я думаю, что они в основном концептуальное понимание.
- Пессимистическая блокировка: когда потоку необходимо работать с общим ресурсом, он сначала блокирует общий ресурс.Когда поток удерживает блокировку ресурса, другие потоки будут заблокированы при работе с ресурсом.блокировать. Например, ключевое слово Synchronized в Java.
- Оптимистическая блокировка: когда потоку необходимо работать с общим ресурсом, он не блокирует его, а оценивает после завершения операции. (Например, оптимистическая блокировка будет контролироваться номером версии, если операция завершенаномер версииЧтобы судить, оперировали ли уже другие потоки общим ресурсом во время работы потока, если да, уведомить операцию о сбое, если нет, операция прошла успешно), конечно, кроме номера версии и CAS, если вы не понимаю, вы можете узнать. На мгновение я не буду вдаваться в подробности.
Управление параллельным доступом к базе данных — MVCC
Многие люди думают, что MVCC — это форма реализации оптимистической блокировки, но я думаю, что MVCC — это просто форма оптимистичной реализации, которая достигается с помощьюАлгоритм видимостиреализовать контроль параллелизма базы данных.
Две формы чтения MVCC
Прежде чем говорить о принципе реализации MVCC, я думаю, необходимо понять две формы чтения MVCC.
-
Чтение моментального снимка: без блокировки считывается только видимая версия текущей транзакции. и ты просто помнишьПростая операция выбора — это чтение моментального снимка (выберите * из таблицы, где id = xxx).
-
Текущее чтение: чтение текущей версии, напримерСпециальные операции чтения, операции обновления/вставки/удаления
Например:
select * from table where xxx lock in share mode, select * from table where xxx for update, update table set.... insert into table (xxx,xxx) values (xxx,xxx) delete from table where id = xxx
Принцип реализации MVCC
MVCC«Три скрытых поля» используются для реализации контроля параллелизма версий. Я проверил много информации и увидел, что есть много блогов, которые говорят, что черезПоле идентификатора создания транзакции и поле идентификатора удаления транзакцииконтролировать выполнение. Но позже обнаружил, что это не очень правильно, давайте взглянем на три реальных скрытых столбца, созданных innoDB, когда MySQL строит таблицу.
RowID | DB_TRX_ID | DB_ROLL_PTR | id | name | password |
---|---|---|---|---|---|
автоматически созданный идентификатор | номер транзакции | указатель отката | id | name | password |
- RowID: скрытый самоувеличивающийся идентификатор.Когда таблица создается без указания первичного ключа, InnoDB будет использовать RowID для создания кластеризованного индекса.
- DB_TRX_ID: идентификатор транзакции, которая последний раз изменяла (обновляла/удаляла/вставляла) эту запись.
- DB_ROLL_PTR: указатель отката, указывающий на предыдущую версию этой записи.
На самом деле, есть также поле флага удаления, которое используется для определения того, была ли запись строки удалена.
И MVCC использует один изПоле транзакции, поле указателя отката, удалить ли поле. Взглянем на текущую таблицу (isDelete взята мной. По официальному заявлению она находится в содержании в начале строки. На самом деле расположение здесь не имеет значения, нужно только знать, что она есть).
isDelete | DB_TRX_ID | DB_ROLL_PTR | id | name | password |
---|---|---|---|---|---|
true/false | номер транзакции | указатель отката | id | name | password |
Итак, как реализовать MVCC через эти три поляАлгоритм видимостиШерстяная ткань?
Почти что-то!undoLog (журнал отката)ипросмотр для чтения.
-
undoLog: журнал отката транзакции является очень важной частью алгоритма видимости и делится на две категории.
- вставить журнал отмены: журнал отмены, созданный транзакцией, вставляющей новые записи, может быть удален сразу после фиксации транзакции.
- обновить журнал отмены: журнал отмены, сгенерированный транзакцией во время обновления или удаления, по-прежнему необходим во время чтения моментального снимка, поэтому его нельзя удалить напрямую.Он может быть удален только тогда, когда система не имеет представления для чтения до этого журнала. ps: Следовательно, длинные транзакции будут генерировать много старых представлений, так что журнал отмен не может быть удален, а место для хранения занято.
-
read-view: Чтение представления является необходимым условием для MySQL, чтобы создать представление за считанные секунды. Например, транзакция создаст представление для чтения, когда она выполняет операцию выбора (чтение моментального снимка). Это представление для чтения на самом деле состоит только из трех полей.
- live_trx_list (сам брал): в системе на момент генерации read-viewИдентификатор активной транзакции.
- up_limit_id: запишите указанный выше live_trx_listминимальный идентификатор транзакции.
- low_limit_id: время генерации чтения-просмотра,Максимальное значение идентификатора транзакции, которая произошла на данный момент + 1.
В это время все готово, только причитается восточный ветер. Позвольте представить самое главноеАлгоритм видимости.
Собственно, основная мысль такова:Как сравнить полученный DB_TRX_ID с тремя атрибутами в представлении для чтения (упомянутыми выше) при создании представления для чтения. Позвольте мне рассказать о трех шагах.Если вы не очень хорошо это понимаете, вы можете обратиться к моей более поздней практике, чтобы понять это.
- Сначала сравните, является ли DB_TRX_ID этой записименьше, чемup_limit_id илиравен текущему идентификатору транзакции. Если оно выполняется, это означает, что текущая транзакция может видеть эту запись. Если он больше, введите следующий раунд суждения
- Затем оцените, является ли DB_TRX_ID этой записибольше или равноидентификатор нижнего предела. Если он больше или равен, это означает, что транзакция не может видеть запись, иначе она войдет в следующий раунд оценки.
- Определить, находится ли DB_TRX_ID записи в массиве активных транзакций.Если есть, то это означает, что запись не была отправлена и невидима для текущей транзакции.Если нет, то значит, она была отправлена, так это видно.
Если эта запись не видна для транзакции и ROLL_PTR не пуста, она будет указывать на адрес указателя отката и использовать отмену журнала, чтобы найти видимую версию записи.
Ниже я нарисовал блок-схему алгоритма видимости
упражняться
Подготовить данные
Сначала я создал очень простую таблицу, только студенческую таблицу с идентификатором и именем.
id | name |
---|---|
Студенческий билет | имя студента |
В это время мы также определяем нужные нам скрытые столбцы, и это становится таким
isDelete | id | name | DB_TRX_ID | DB_ROLL_PTR |
---|---|---|---|---|
Это удалено | Студенческий билет | имя студента | Создайте идентификатор транзакции, который удаляет и обновляет запись | указатель отката |
В это время вставьте три строки данных и измените данные таблицы на следующие.
isDelete | id | name | DB_TRX_ID | DB_ROLL_PTR |
---|---|---|---|---|
false | 1 | Сяо Мин | 1 | null |
false | 2 | Сяо Фан | 1 | null |
false | 3 | Сяо Чжан | 1 | null |
Пример 1
Любой, кто использовал MySQL, знает, что из-за изоляции данные, полученные транзакцией B, должны быть такими.
id | name |
---|---|
1 | Сяо Мин |
2 | Сяо Фан |
3 | Сяо Чжан |
Почему незафиксированные изменения транзакции A не видны транзакции B, как это делает MVCC? Давайте поэкспериментируем с алгоритмом видимости прямо сейчас.
Во-первых, транзакция A открывает транзакцию (конечно, это не открытая. В режиме RR настоящее чтение-представление получается, когда выполняется чтение первого снапшота). Предположим, что транзакция A имеет идентификатор транзакции 2, а транзакция B имеет идентификатор 3.
Затем транзакция A выполняет операцию обновления. Как показано на рисунке, операция обновления создает новую версию, а указатель отката новой версии указывает на старую версию (обратите внимание, что в журнале отмены фактически хранится логический журнал, здесь для удобства я запишите его непосредственно как физический журнал).
Наконец, транзакция B выполняет чтение моментального снимка.Обратите внимание, что это основное внимание нашего анализа.
首先,在进行快照读的时候我们会创建一个 read-view (忘记回去看一下那三个字段)
这个时候我们的 read-view 是
up-limit-id = 2
alive-trx-list = [2,3]
low-limit-id = 4
然后我们获取那两个没有被修改的记录(没有顺序,这里为了一起解释方便)
我们获取到(2,小方)和(3,小张)这两条记录,发现他们两的 DB_TRX_ID = 1
我们先判断 DB_TRX_ID 是否小于 up-limit-id 或者等于当前事务id
发现 1<2 小于 up-limit-id ,则可见 直接返回视图。
然后我们获取更改了的数据行
其实你也发现了这是一个链表,此时链表头的 DB_TRX_ID 为 2
我们进行判断 2 < 2 不符合,进入下一步判断
判断 DB_TRX_ID >= low_limit_id 发现此时是 2 >= 4 不符合 故再进入下一步
此时判断 Db_TRX_ID 是否在 alive_trx_list 活跃事务列表中,发现这个 DB_TRX_ID
在活跃列表中,所以只能说明该行记录还未提交,不可见。
最终判断不可见之后通过回滚指针查看旧版本,发现此时 DB_TRX_ID 为1
故再次进行判断 DB_TRX_ID < up-limit-id ,此时 1 < 2 符合 ,所以可见并返回
所以最终返回的是
id | name |
---|---|
1 | Сяо Мин |
2 | Сяо Фан |
3 | Сяо Чжан |
Давайте еще раз проверим. На этот раз мы отправим транзакцию A, воссоздадим транзакцию C и выберем.
Наш ожидаемый результат должен быть примерно таким
id | name |
---|---|
1 | таракан |
2 | Сяо Фан |
3 | Сяо Чжан |
Схема этой операции выглядит следующим образом
А пока давайте проанализируем представление для чтения, созданное транзакцией c.
В это время транзакция A была зафиксирована, поэтому транзакция A не находится в массиве активных транзакций. В это время три свойства чтения-просмотра должны быть
up-limit-id = 3
alive-trx-list = [3,4]
low-limit-id = 5
- Как и выше, мы сначала получаем две записи (2, Xiaofang) и (3, Xiaozhang) и обнаруживаем, что их DB_TRX_ID = 1, в это время 1
- Затем мы получаем строку записи с идентификатором 1, которая только что была изменена, и обнаруживаем, что DB_TRX_ID в начале связанного списка равен 2. В это время 2
Таким образом, окончательный возврат
id | name |
---|---|
1 | таракан |
2 | Сяо Фан |
3 | Сяо Чжан |
Пример 2
Чтобы углубить наше понимание, давайте используем относительно сложный пример для проверкиАлгоритм видимости.
Сначала мы удаляем запись в транзакции A, которая становится следующей.
Затем вставляется транзакция B, поэтому она становится следующей.
Затем транзакция B выполняет операцию выбора, и мы можем обнаружить, что в это время вся таблица фактически станет такой, что эта операция выбора будет выбрана.
Режим чтения в это время
up-limit-id = 2
alive-trx-list = [2,3,4]
low-limit-id = 5
В это время мы будемСнимок прочитан, во-первых, две предыдущие записи Сяомин и Сяофанг одинаковые, в это время DB_TX_ID равен 1. Мы можем судить, что DB_TX_ID = 1 = low-limit-id не установлен, затем введите окончательный раунд, чтобы определить, есть ли он в списке активных транзакций, обнаружил, что DB_TX_ID = 2 не виден в live-trx-list = [2,3,4] (Если он виден, он будет знать, что предыдущий флаг удаления был удален, а возврат пуст.), запись предыдущей версии находится по указателю отката.В это время, если DB_TX_ID = 1 виден, как указано выше, строка возвращается.
Последний, кто оценивает запись Xiaoliang, виден и возвращается, потому что DB_TX_ID = current_tx_id (идентификатор текущей транзакции).
Таблица, возвращенная в это время, выглядит так
id | name |
---|---|
1 | Сяо Мин |
2 | Сяо Фан |
3 | Сяо Чжан |
4 | Маленький свет |
Затем транзакция А выполняет операцию выбора, мы можем знать, что текущее чтение-представление
up-limit-id = 2
alive-trx-list = [2,3,4]
low-limit-id = 5
Затем вы видите то же самое, что и выше
В это время мы будемСнимок прочитан, во-первых, две предыдущие записи Сяомин и Сяофанг одинаковые, в это время DB_TX_ID равен 1. Мы можем судить, что DB_TX_ID = 1 isDeleteЕсли флаг истинный, то это означает, что он был удален и возвращается пустым, и то же самое верно для четвертого маленького яркого Judge DB_TX_ID = 4 = low-limit-id = 5 Если не установлено, переходим к последнему шагу и обнаруживаем, что его не видно в массиве активных транзакций и указатель отката этой записи нулевой, поэтому возвращает нуль .
Тогда список, возвращаемый в это время, должен быть таким
id | name |
---|---|
1 | Сяо Мин |
2 | Сяо Фан |
Хотя есть что анализировать, чем больше, тем лучше, чем больше вы знакомы, тем лучше вы можете понять этот алгоритм.
После этого выполняется транзакция C.Снимок прочитанработать. Во-первых, вид все еще выглядит так
Тогда представление для чтения для транзакции C будет
up-limit-id = 2
alive-trx-list = [2,3,4]
low-limit-id = 5
Две записи Xiaoming и Xiaofang видны как указано выше.Я не буду повторять анализ здесь, а затем для записи Xiaozhang DB_TX_ID = 2 = low-limit-id = 5 еще более неверно. откатите указатель и обнаружите, что он виден, и вернитесь. То же самое относится и к последнему небольшому свету Наконец, будет обнаружено, что DB_TX_ID = 3 также находится в активном массиве транзакций, поэтому он не виден.
Таким образом, результатом транзакции C select является
id | name |
---|---|
1 | Сяо Мин |
2 | Сяо Фан |
3 | Сяо Чжан |
Позже и транзакция A, и транзакция B выполнили действие фиксации, а одна транзакция D выполнила чтение моментального снимка.В настоящее время представление остается прежним.
Но вид чтения в это время изменился
up-limit-id = 4
alive-trx-list = [4,5]
low-limit-id = 6
Сначала судим записи Сяомина и Сяофана - видимые (не пояснено), запись Сяо Чжана DB_TX_ID=2 Наконец (действительно последний, это непросто!), транзакция C однажды выполнила операцию выбора.Потому что в режиме RR read-view определяется при чтении первого снапшота, поэтому представление для чтения в это время не будет изменено, а затем не будет изменено и предыдущее представление, поэтому, даже если предыдущая транзакция A и транзакция B были зафиксированы в это время, это не повлияет на результат выбора транзакция C в это время. Так что результат должен быть Подведем итоги. Фактически, MVCC реализует контроль параллелизма версий через «три» скрытых поля (идентификатор транзакции, указатель отката, флаг удаления), а также журнал отмен и алгоритмы видимости.. Для того, чтобы вы еще раз подробно поняли этот алгоритм, я снова выложу эту картинку
id
name
1
Сяо Мин
2
Сяо Фан
4
Маленький свет
id
name
1
Сяо Мин
2
Сяо Фан
3
Сяо Чжан
Суммировать