Транзакции базы данных и многоверсионный контроль MVCC

база данных

Особенности сделки

  • атомарность

    Транзакция должна рассматриваться как неделимая минимальная единица работы, и все операции во всей транзакции либо успешно фиксируются, либо все завершаются с ошибкой и откатываются.

  • Последовательность

    База данных всегда переходит из одного непротиворечивого состояния в другое и должна находиться в непротиворечивом состоянии до и после выполнения транзакции.

  • Изоляция

    Как правило, изменения, сделанные одной транзакцией, не видны другим транзакциям, пока они не будут окончательно зафиксированы. Что касается изоляции транзакций, база данных обеспечивает различные уровни изоляции.

  • Долговечность

    Как только транзакция фиксируется, ее модификации постоянно сохраняются в базе данных. Даже если в системе базы данных произойдет сбой, она не будет потеряна.

Проблемы с одновременными транзакциями

  • грязное чтение

Транзакция изменяет запись. До того, как транзакция будет завершена и зафиксирована, данные этой записи находятся в несогласованном состоянии. В это время другая транзакция также читает ту же запись.Если она не контролируется, вторая транзакция считывает «грязные» данные и соответственно выполняет дальнейшую обработку, что приводит к незафиксированной зависимости данных.

время Транзакция А Транзакция Б
T1 открытая транзакция открытая транзакция
T2 Баланс аккаунта запроса 1000
T3 Пополнение 500, баланс изменен на 1500
T4 Баланс запроса1500
T5 Отменить транзакцию, изменить баланс обратно1000
T6 Импорт 500, баланс изменен на2000
T7 совершить транзакцию
  • неповторяемое чтение

В определенный момент после чтения некоторых данных транзакция снова считывает ранее прочитанные данные, но обнаруживает, что прочитанные данные были изменены, либо какие-то записи были удалены.

время Транзакция А Транзакция Б
T1 открытая транзакция открытая транзакция
T2 выберите * от пользователя, где user_id=100 считается информацией о пользователе Xiaomi
T3 Измените возраст, соответствующий информации о пользователе user_id=100, на18
T4 совершить транзакцию
T5 Повторите запрос, чтобы найтиизменение возрастаохватывать
T6 ...
T7 совершить транзакцию
  • галлюцинации

Транзакция повторно считывает ранее извлеченные данные с теми же условиями запроса только для того, чтобы обнаружить, что другие транзакции вставили новые данные, удовлетворяющие условиям ее запроса.

время Транзакция А Транзакция Б
T1 открытая транзакция открытая транзакция
T2 выберите * от пользователя, где возраст = 18, предположим, чтобы получить две записи
T3 Вставьте новую запись с возрастом = 18 в пользовательскую таблицу.
T4 совершить транзакцию
T5 Запросите еще раз, чтобы получить три записи
T6 ..
T7 совершить транзакцию

Разница между фантомным чтением и неповторяемым чтением

  • Ключевым моментом неповторяемого чтения является модификация: в одной и той же транзакции при одинаковых условиях данные, считанные в первый и во второй раз, несовместимы (в середине есть другие транзакции, которые зафиксировали модификацию).
  • При фантомном чтении основное внимание уделяется добавлению или удалению: в одной и той же транзакции при одинаковых условиях количество записей, прочитанных в первый и второй раз, различается (в середине есть другие транзакции, которые отправили новые или удаленные записи). записи).

Уровень изоляции транзакции

Стандарт SQL определяет четыре типа уровней изоляции, каждый из которых определяет изменения, сделанные в рамках транзакции, видимые внутри и между транзакциями и невидимые.

  • Read Uncommited

Все транзакции могут видеть результаты выполнения других незафиксированных транзакций, и этот уровень изоляции обычно не используется.

  • Чтение подтверждено (RC)

Транзакция может видеть только изменения, сделанные зафиксированными транзакциями.

  • Повторяемое чтение (RR)

Гарантирует, что несколько экземпляров одной и той же транзакции видят одни и те же строки данных при одновременном чтении данных.

  • Serializable

Полностью сериализованное чтение, для каждого чтения требуется общая блокировка на уровне таблицы, а операции чтения и записи блокируют друг друга.

уровень изоляции грязное чтение неповторяемое чтение галлюцинации
Read Uncommited Yes Yes Yes
Read Committed No Yes Yes
Repeatable Read No No Yes
Serializable No No No

Решения для параллельных транзакций

Грязные чтения, неповторяемые чтения и фантомные чтения — все это проблемы согласованности чтения базы данных, которые должны быть решены базой данных, обеспечивающей определенный механизм изоляции транзакций.

(1)замок механизм

решатьпиши-пишиконфликтные вопросы. Перед чтением данных заблокируйте их, чтобы предотвратить изменение данных другими транзакциями.

  • пессимистический замок

    Часто полагаются на механизм блокировки, предоставляемый базой данных.

  • оптимистическая блокировка

    Большинство из них реализованы на основе механизма записи версии данных.

(2)Многоверсионный контроль параллелизма MVCC

решатьчитай пишиконфликтные вопросы. Без блокировки непротиворечивый снимок данных в момент запроса данных генерируется через определенный механизм, и этот снимок используется для обеспечения согласованного чтения на определенном уровне (уровень оператора или уровень транзакции). Таким образом, операцию записи не нужно блокировать во время операции чтения, а операцию чтения не нужно блокировать во время операции записи.

Многоверсионный контроль параллелизма MVCC

Большинство реализаций транзакционного механизма хранения Mysql не являются простыми блокировками на уровне строк.Основываясь на соображениях производительности параллелизма, обычно реализуется управление параллелизмом с несколькими версиями MVCC. MVCC реализуется путем сохранения моментального снимка данных в определенный момент времени. Данные, видимые транзакцией, непротиворечивы независимо от того, сколько времени требуется для выполнения транзакции.

операция чтения

Операции чтения делятся на две категории: чтение моментальных снимков и текущее чтение.

Снимок прочитан: Простая операция выбора представляет собой чтение моментального снимка и не блокируется.

  • select * from table where ? ;

текущее чтение: Специальные операции чтения, операции вставки/обновления/удаления относятся к текущему чтению и должны быть заблокированы.

  • select * from table where ? lock in share mode ;
  • select * from table where ? for update ;
  • update table set ? where ? ;
  • delete from table where ? ;

хранилище данных

В механизме хранения innodb каждая строка данных содержит несколько скрытых полей: DB_ROW_ID, DB_TRX_ID, DB_ROLL_PTR и DELETE_BIT.

数据库存储结构

  • DB_TRX_ID: идентификатор, используемый для идентификации транзакции, которая изменила запись этой строки в последний раз, то есть идентификатор транзакции, которая изменила запись этой строки в последний раз. Внутри операция удаления является операцией обновления, которая обновляет флаг удаления DELELE_BIT в строке.
  • DB_ROLL_PTR: указывает на текущие данныеundo logЗапись, откат данных через этот указатель, чтобы найти информацию о содержимом до того, как запись была обновлена.
  • DB_ROW_ID: содержит идентификатор строки, который монотонно увеличивается по мере вставки новых строк.Когда кластерный индекс автоматически генерируется innodb, кластерный индекс будет включать значение этого идентификатора строки, в противном случае этот идентификатор строки не будет отображаться ни в одном индексе.
  • DELELE_BIT: используется для определения того, удалена ли запись.

манипуляция данными

  • insert

    Создайте запись, DB_TRX_ID — идентификатор текущей транзакции, DB_ROLL_PTR — NULL.

  • delete

    Установите DB_TRX_ID текущей строки на текущий идентификатор транзакции, а DELELE_BIT на 1.

  • Обновить Скопируйте строку, DB_TRX_ID новой строки — это идентификатор текущей транзакции, DB_ROLL_PTR указывает на запись предыдущей версии, а DB_ROLL_PTR устанавливается в NULL после фиксации транзакции.

  • select

    1. Найдите только те записи, которые были созданы до текущего идентификатора транзакции, и убедитесь, что все строки, прочитанные текущей транзакцией, существовали до транзакции или были созданы или изменены текущей транзакцией;

    2. Когда DELETE BIT строки равен 1, найдите и удалите записи, которые старше идентификатора текущей транзакции, чтобы гарантировать, что строка не будет удалена до начала текущей транзакции.

последовательное чтение

Непротиворечивое чтение Mysql достигается за счет структуры представления чтения. представление чтения в основном используется для оценки видимости, оно поддерживаетДругие в настоящее время активные транзакции, невидимые для этой транзакции. где самый ранний идентификатор транзакцииup_limit_id, последний идентификатор транзакцииlow_limit_id.

	trx_id_t	low_limit_id;
				/*!< The read should not see any transaction
				with trx id >= this value. In other words,
				this is the "high water mark". */
	trx_id_t	up_limit_id;
				/*!< The read should see all trx ids which
				are strictly smaller (<) than this value.
				In other words,
				this is the "low water mark". */

Как понять low_limit_id

Вы можете обратиться к этому ответу, чтобы понять. low_limit_id должен бытьИдентификатор следующей транзакции, еще не присвоенный текущей системой(Легче понять из этой семантики), то естьМаксимальное значение идентификатора транзакции, которое произошло на данный момент +1.

Как MySQL достигает неблокирующего чтения при уровне изоляции RC?Ха-ха, смейтесь, ответ Бай Мэйшэна

low_limit_id理解

Оценка видимости

Предполагая, что идентификатор последней зафиксированной транзакции строки, которую нужно прочитать (то есть идентификатор стабильной транзакции текущей строки данных), равен trx_id, процесс сравнения видимости выглядит следующим образом:

  1. trx_id < up_limit_id =>Последняя модификация этой записи перед созданием представления для чтения, переход к шагу 5;
  2. trx_id > low_limit_id =>Последняя модификация этой записи после создания представления для чтения, переход к шагу 4;
  3. up_limit_id <= trx_id <= low_limit_id =>Переходим от up_limit_id к low_limit_id, если trx_id равен одному из них, значит последняя модификация записи не сохранилась, и переходим к шагу 4. В противном случае перейдите к шагу 5;
  4. Из журнала отмен, на который указывает указатель DB_ROLL_PTR этой записи (последняя модификация этой записи), назначьте DB_TRX_ID журнала отмен для trx_id и перейдите к шагу 1, чтобы перезапустить расчет видимости;
  5. Если DELELE_BIT этой записи ложный, это означает, что запись не была удалена и может быть возвращена, иначе она не будет возвращена.

Уровни изоляции RR и RC

Уровни изоляции Repeatable Read и Read Committed реализованы на основе представления чтения, разница в следующем:

  • Repeatable Read

    Представление для чтения создается в момент выполнения первого оператора select в транзакции, и все последующие выборки повторно используют этот объект, поэтому можно гарантировать непротиворечивость каждого чтения. (Повторяемая семантика чтения)

  • Read Committed

    Каждый оператор select в транзакции создаст представление для чтения, чтобы вы могли прочитать содержимое, зафиксированное другими транзакциями.

Для InnoDB, хотя Repeatable Read имеет более высокий уровень изоляции, чем Read Committed, накладные расходы относительно невелики.

использованная литература

Сводка транзакций базы данных и транзакций MySQL

Многоверсионный контроль MySQL-InnoDB-MVCC

Углубленный анализ MySQL InnoDB MVCC

В чем разница между оптимистической блокировкой и MVCC?

Как MySQL достигает неблокирующего чтения при уровне изоляции RC?