Управление многоверсионным параллелизмом (MVCC) — это технология, используемая для повышения производительности одновременного выполнения баз данных, которая особенно эффективна при выполнении операций чтения и записи с высоким уровнем параллелизма. MVCC позволяет избежать конфликтов чтения и записи, поддерживая несколько версий данных, поэтому операции чтения не должны блокировать операции записи, а операции записи не влияют на операции чтения. Ниже мы подробно объясняем принцип реализации MVCC механизмом хранения InnoDB в MySQL.
MVCC (Multi-Version Concurrency Control) можно рассматривать как улучшение блокировки на уровне строк, которое в основном обеспечивает одновременный доступ к данным за счет сохранения нескольких версий данных в разные моменты времени. MVCC часто используется для реализации оптимистических стратегий блокировки, контроля согласованности данных с помощью номеров версий и предотвращения узких мест в производительности, вызванных блокировками.
Интересно, задумывались ли вы когда-нибудь над таким вопросом: почему в повседневных операциях операции чтения и записи не могут блокировать друг друга?
До появления технологии MVCC, чтобы гарантировать отсутствие исключений данных между несколькими транзакциями на определенном уровне изоляции, для управления параллелизмом была необходима блокировка.
Например, когда транзакция А читает строку данных, другие транзакции не могут изменить эту строку данных, поскольку это может привести к тому, что транзакция А прочитает противоречивые данные.
Основное преимущество MVCC заключается в том, что он решает проблему блокировки между операциями чтения и записи, тем самым значительно улучшая параллелизм транзакций. Далее мы используем пример, чтобы постепенно изучить реализацию MVCC в MySQL.
Давайте посмотрим на пример на рисунке 1;
Ключом к ответу на этот вопрос является уровень изоляции транзакции. Поведение при различных уровнях изоляции выглядит следующим образом:
column= lisi
。column= zhangsan
,Но после того, как существование будет представлено,Запросрезультатстановитьсяcolumn= lisi
。
column= zhangsan
。Ниже приведена сравнительная таблица запросов и операторов уровня изоляции базы данных модификации в MySQL 5.7 и MySQL 8.0:
действовать | MySQL 5.7 | MySQL 8.0 |
---|---|---|
Запросить текущий уровень изоляции сеанса | ВЫБЕРИТЕ @@tx_isolation; или ПОКАЗАТЬ ПЕРЕМЕННЫЕ, КАК 'transaction_isolation'; | ВЫБЕРИТЕ @@transaction_isolation; или ПОКАЗАТЬ ПЕРЕМЕННЫЕ, КАК 'transaction_isolation'; |
Запросить глобальный уровень изоляции | ВЫБЕРИТЕ @@global.tx_isolation; или ПОКАЗАТЬ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ, КАК 'transaction_isolation'; | ВЫБЕРИТЕ @@global.transaction_isolation; или ПОКАЗАТЬ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ, КАК 'transaction_isolation'; |
Изменить текущий уровень изоляции сеанса | SET SESSION TRANSACTION ISOLATION LEVEL уровень изоляции; | SET SESSION TRANSACTION ISOLATION LEVEL уровень изоляции; |
Изменить глобальный уровень изоляции | SET GLOBAL TRANSACTION ISOLATION LEVEL уровень изоляции; | SET GLOBAL TRANSACTION ISOLATION LEVEL уровень изоляции; |
Среди них уровень изоляции может быть одним из следующих:
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
(MySQLпо умолчанию)SERIALIZABLE
существуют Здесь мы пока не будем обсуждать характеристики базы данных изACID, а дасосредоточиться навопрос:данные о существовании были изменены,Как база данных гарантирует, что результаты запроса сохранят предыдущее значение?
Это достигается с помощью журналов отмены и технологии MVCC в базе данных, как показано на рисунке 1-1.
MVCC в InnoDB в основном опирается на следующие три скрытых столбца, которые поддерживаются в каждой строке записей для обеспечения многоверсионного управления параллелизмом:
DB_TRX_ID
,то есть идентификатор транзакции,Записывает последнюю вставку строкииливозобновлятьиз делID。когда это необходимосудить о Когда запись да в деле видна, InnoDB Сравнение будет производиться на основе столбца, текущей транзакции и представления.DB_ROLL_PTR
да Указатель отката, указывающий на предыдущую версию записи строки. существуют При обновлении данных InnoDB Записи старых версий будут сохранены и связаны с помощью этих указателей для поддержки поиска предыдущих версий данных посредством отката. Это да понимает MVCC Ключ к многоверсионному хранилищу.DB_ROW_ID
да Автоматически увеличивающийся идентификатор строки, используемый для уникальной идентификации каждой строки данных при отсутствии явного первичного ключа. хотя DB_ROW_ID
существовать MVCC Механизм не контролирует параллелизм напрямую.,Но он играет важную роль в управлении записями строк и их позиционировании.,Особенно когда дасуществовать не определяет первичный ключ.Эти три скрытых столбца совместно поддерживают InnoDB из MVCC выполнить,Обеспечить существование в сценариях с высоким уровнем параллелизма.,Чтение и запись могут выполняться параллельно, не блокируя друг друга.
При вставке фрагмента данных Соответствующий указатель сегмента отката в существующей записи имеет значение NULL. Как показано на рисунке 1-2.
При обновлении записи исходная запись сохраняется в Undo В табличном пространстве можно прочитать измененные данные, которые не были отправлены во время запроса. Undo Добиться этого можно в старой версии табличного пространства. Несколько версий данных связаны через структуру связанного списка, образуя цепочку версий. MySQL Прохождение рекордаизуказатель отката(DB_ROLL_PTR
)иделаID(DB_TRX_ID
)чтобы определить версию данныхизвидимыйсекс。специфический Процесс принятия решенияследующее:
существуют в начале каждой транзакции,Система скопирует всю текущую информацию об активной транзакции в список.,называетсяRead View。При чтении записей,Будет основано на записях TRX_ID
и Read View Самый крупный в Китае TRX_ID
минимальная сумма TRX_ID
Сравните, чтобы определить, видна ли запись для текущей транзакции.
TRX_ID
меньше, чем Read View Средний и самый маленький TRX_ID
******:**
Описание записи существует Read View серединаизвседела Отправьте заявку, прежде чем начать,таким образом, видимый для текущей транзакции,Данные могут быть возвращены напрямую.TRX_ID
больше, чем Read View Самый крупный в Китае TRX_ID
******:**
Описание записи существуетдела Изменено после запуска。этотчаснеобходимо основываться науказатель отката Найти предыдущую версиюиз Записывать,и сделай это TRX_ID
Присвойте значение текущей строке и повторите оценку.TRX_ID
роды Read View В пределах:Необходимо дальнейшее решение:
TRX_ID
существовать Read View серединажитьсуществовать:TRX_ID
Сделайте следующий раунд суждения.TRX_ID
Нетсуществовать Read View середина:Read View да MySQL InnoDB Двигатель используется для реализации Многоверсионный параллельный контроль (MVCC) из Ключевые механизмы. Он существует, чтение выполнения транзакции Одновременно создается снимок, чтобы гарантировать, что транзакции могут видеть согласованное и стабильное представление данных. Читать View Записывает состояние системы, когда транзакция создает снимок, особенно все транзакции. транзакцияиз ID список. проходить Read View,База данных может гарантировать, что транзакция видит только те данные, которые были зафиксированы при создании представления.,На него не повлияют другие последующие дела.
SELECT ... LOCK IN SHARE MODE
, SELECT ... FOR UPDATE
, UPDATE
, INSERT
, DELETE
ждать.SELECT
действовать,оно проходит Read View
выполнить,Убедитесь, что транзакции считывают полную версию данных при создании моментального снимка.,Вместо того, чтобы изменять его после да.SELECT
действовать, существовать, уровень изоляции считается зафиксированным (Read Committed) или повторяемое чтение (Repeatable Read) особенно распространено.Четыре поля просмотра чтение определяет выполнение транзакции существованиечтение снимка Какие данные ему видны, а какие Невидимый.
trx_ids:
low_limit_id:
up_limit_id:
creator_trx_id:
Read View
Вышеупомянутые четыре поля используются для управления видимостью снимков транзакций и обеспечения существования транзакции. снимкачасизпоследовательныйсекс。существовать MySQL из MVCC выполнитьсередина,Этот механизм очень важен,Потому что это обеспечивает изоляцию транзакций и их реализацию в средах с высоким уровнем параллелизма.,Предотвратите грязное чтение, неповторяемое чтение и фантомное чтение.
существовать MySQL 8.0 из Исходный кодсередина,Read View
Основной код в основном включает в себя InnoDB двигатель хранения раздел администратора дел. они определяют Read View
генерация, инициализация поля, оценка видимости и другие функции.
read_view_open_now
функцияфункция read_view_open_nowda используется для создания нового изображения. Read Вид. Он запишет текущие активные транзакции и инициализирует Read View из Каждое поле.
read_view_t* read_view_open_now(trx_t* trx) {
read_view_t* view;
view = static_cast<read_view_t*>(ut_malloc_nokey(sizeof(*view)));
ut_a(view != NULL);
/* Настроить создающую транзакцию ID */
view->creator_trx_id = trx->id;
/* Будьте в курсеактивная список транзакций и назначить view */
view->m_trx_ids = trx_sys_get_active_trx_ids();
/* активная транзакцияизколичество */
view->trx_list_len = trx_sys->rw_trx_list_len;
/* Установить низкий уровень воды */
view->low_limit_no = trx_sys->rw_trx_list->start->id;
/* Установить высокий уровень воды */
view->up_limit_no = trx_sys->rw_trx_list->end->id;
return(view);
}
trx_sys_get_active_trx_ids
функцияфункция trx_sys_get_active_trx_ids используется для получения всей активности в текущей системе. транзакцияиз ИДЕНТИФИКАТОР. Эта функция возвращает список, содержащий все незафиксированные транзакции. ID из списка транзакций из изменений в текущих Read View Невидимый.
trx_id_t* trx_sys_get_active_trx_ids() {
trx_id_t* trx_ids;
/* выделено для транзакций хранения ID из Объем памяти */
trx_ids = static_cast<trx_id_t*>(ut_malloc_nokey(trx_sys->rw_trx_list_len * sizeof(trx_id_t)));
/* Пересечь течениеактивная список транзакций, сохраняет каждую транзакцию из ID */
rw_trx_list_lock();
rw_trx_t* rw_trx = trx_sys->rw_trx_list->start;
for (size_t i = 0; i < trx_sys->rw_trx_list_len; i++, rw_trx = rw_trx->next) {
trx_ids[i] = rw_trx->id;
}
rw_trx_list_unlock();
return trx_ids;
}
read_view_sees_trx_id
функцияфункция read_view_sees_trx_idиспользуется длясудить о деле ID изменено на текущий Read View видно. это основано на Четыре поля просмотра чтение для определения наглядности.
bool read_view_sees_trx_id(read_view_t* view,trx_id_t trx_id) {
/* еслидела ID меньше, чем up_limit_id, указывающий на существование транзакции Read View Он был отправлен до сборки, поэтому его видно. */
if (trx_id < view->up_limit_no) {
return true;
}
/* еслидела ID больше, чемили равно low_limit_id, указывающий, что транзакция существует Read View Запускается после генерации, поэтому не видно */
if (trx_id >= view->low_limit_no) {
return false;
}
/* еслидела ID существовать active_trx_ids Перечислите, опишите даактивная одна из транзакций и поэтому невидима */
for (size_t i = 0; i < view->trx_list_len; i++) {
if (view->m_trx_ids[i] == trx_id) {
return false;
}
}
/* если Если ни одно из вышеперечисленных условий не выполнено, транзакция видна */
return true;
}
read_view_close
функцияфункция read_view_close используется для закрытия и уничтожает одно Read Посмотреть, освободить память.
void read_view_close(read_view_t* view) {
ut_free(view->m_trx_ids);
ut_free(view);
}
создавать Read View
(read_view_open_now
):
Получайте активные транзакции ID (trx_sys_get_active_trx_ids
):
Определите видимость транзакции (read_view_sees_trx_id
):
закрытие Read View
(read_view_close
):
Эти фрагменты основного кода демонстрируют InnoDB Как пройти Read View
Внедрите чтение снимков, чтобы обеспечить изоляцию и согласованность транзакций.
существует Navicat. Выполните следующее в SQL и подготовьте простую тестовую таблицу:
CREATE TABLE test_mvcc (
id INT PRIMARY KEY,
value VARCHAR(50)
) ENGINE=InnoDB;
INSERT INTO test_mvcc (id, value) VALUES (1, 'Initial Value');
существовать Navicat Откройте два окна запросов и смоделируйте два сеанса транзакций.
сессия 1(запускатьделаивозобновлять Записывать):
START TRANSACTION;
UPDATE test_mvcc SET value = 'Updated Value by Session 1' WHERE id = 1;
-- На данный момент транзакция не отправлена, а данные только для сессии. 1 видимый
сессия 2(запускатьделаи Запрос Записывать):
START TRANSACTION;
SELECT * FROM test_mvcc WHERE id = 1;
-- В это время сессия 2 надо еще посмотреть 'Initial Value», потому что сессия 1 из дел Не отправлено
существованиясессия 1 Перед совершением транзакции данные передаются другим транзакциям Невидимый.
сессия 1 Отправить транзакцию:
COMMIT;
сессия 2 Запрос еще раз:
SELECT * FROM test_mvcc WHERE id = 1;
-- сейчассуществоватьсессия 2 Вы можете увидеть обновленное значение 'Updated Value by Session 1'
может пройтиэтот Экспериментальное наблюдениеделамеждуизизоляциясекси Записыватьизвидимыйсекс,Объедините следующее MySQL Встроенная команда для просмотра более подробной информации:
-- Проверять InnoDB из статус дел
SHOW ENGINE INNODB STATUS;
-- Проверятьтекущийделаиз ID Уровень изоляции
SELECT @@TRANSACTION_ISOLATION, @@tx_isolation;
Navicat Может помочь существовать интуитивно управлять несколькими сессиями в графическом интерфейсе, но на уровне отладки кода, например, трассировки MySQL Конкретный процесс оценки видимости в исходном коде требует использования GDB и другие инструменты.
Здесь необходимо объяснить одну вещь, Для разных из делуровень изоляции, видимыйсексизвыполнить也Нет一样。
Ссылки: https://dev.mysql.com/blog-archive/mysql-8-0-mvcc-of-large-objects-in-innodb/