redo log
Поддержка транзакций является одной из важных характеристик базы данных, отличающих файловую систему.Три характеристики транзакций:
- Атомарность: все операции либо выполняются, либо не выполняются, неделимы.
- Непротиворечивость: результат перехода базы данных из одного состояния в другое в конечном счете непротиворечив. Например, A передает 500 в B, A получает на 500 меньше, а B получает на 500 больше, но значение A+B имеет не изменился. .
- Изоляция: Транзакции и транзакции заранее изолированы друг от друга и не мешают друг другу.
- Долговечность: как только транзакция зафиксирована, ее изменения в данных являются постоянными.
В этой статье в основном говорится о знаниях, связанных с настойчивостью.
Когда мы обновляем запись в транзакции, например:
update user set age=11 where user_id=1;
Его процесс примерно таков:
- Сначала определите, находится ли страница, где находятся данные user_id, в памяти, если нет, то сначала прочитайте ее из базы данных, а затем загрузите в память
- Изменить возраст в памяти на 11
- Запись в журнал повторов, а журнал повторов находится в состоянии подготовки
- написать в бинлог
- Зафиксируйте транзакцию, журнал повторов станет состоянием фиксации
Здесь есть несколько ключевых моментов: Что такое журнал повторов? Зачем нужен журнал повторов? Что такое журнал повторов в состоянии подготовки? Может ли журнал повторов и бинлог быть лишь одним из них?.. С помощью этой серии вопросов давайте приоткроем завесу журнала повторов.
Зачем сначала обновлять данные памяти, а не напрямую обновлять данные диска?
Почему бы нам не обновлять соответствующие данные диска напрямую каждый раз, когда мы обновляем данные? Во-первых, мы знаем, что дисковый ввод-вывод медленный, память быстрая, и скорость этих двух процессов неодинакова.Затем для медленного дискового ввода-вывода существует индекс.Посредством индексирования, даже если есть миллионы данные, мы все еще можем использовать их на диске.Найти наши данные очень быстро, это роль индекса. Однако индекс также необходимо поддерживать, и он не является статическим.Когда мы вставляем новые данные A, поскольку эти данные должны быть вставлены после существующих данных B, тогда данные B должны быть перемещены, чтобы дать позицию A ...Это есть определенные накладные расходы. Что еще хуже, вставляемая страница уже заполнена, поэтому необходимо подать заявку на новую страницу, а затем часть данных перемещается в прошлое.Это называется разбиением страницы, и накладные расходы еще больше. Если наше изменение sql заключается в непосредственном изменении данных на диске, и возникает вышеуказанная проблема, то эффективность в это время будет очень низкой, а если она серьезная, это вызовет тайм-аут. Процесс обновления сначала загружает соответствующую страницу данных в память, а затем сначала обновляет данные в памяти. Для mysql все изменения должны сначала обновить данные в пуле буферов, а затем грязные страницы в пуле буферов будут с определенной периодичностью сбрасываться на диск (checkPointмеханизм), оптимизируйте разрыв между ЦП и диском через пул буферов, чтобы общая производительность не падала слишком быстро.
Зачем нужен журнал повторов?
Буферный пул может помочь нам устранить разрыв между процессором и диском, а механизм контрольных точек может обеспечить окончательное размещение данных, однако, поскольку контрольная точка не срабатывает при каждом ее изменении, она обрабатывается главным потоком на интервалы. Таким образом, в худшем случае сразу после записи в буферный пул база данных выходит из строя, тогда этот фрагмент данных теряется и не может быть восстановлен. В этом случае D в ACID не выполняется.Чтобы решить проблему сохраняемости в этом случае, транзакция механизма InnoDB использует технологию WAL (Write-Ahead Logging).Идея этой технологии состоит в том, чтобы записать сначала журнал, а затем запись на диск.Только когда журнал успешно записан, транзакция может быть успешно зафиксирована, и журнал здесь является журналом повторов. Когда происходит время простоя и данные не сбрасываются на диск, их можно восстановить с помощью журнала повторов, чтобы обеспечить D в ACID, который является ролью журнала повторов.
Как реализован журнал повторов?
Запись журнала повторов не записывается напрямую на диск. Журнал повторов также имеет буфер, называемый буфером журнала повторов (буфер журнала повторов). Механизм InnoDB будет сначала записывать буфер журнала повторов при записи журнала повторов, а затем также использовать определенное количество времени Частота сбрасывается в реальный журнал повторов, буфер журнала повторов обычно не должен быть очень большим, это просто временный контейнер, главный поток будет сбрасывать буфер журнала повторов в файл журнала повторов каждую секунду, поэтому нам нужно только убедиться, что буфера журнала повторов достаточно для сохранения объема данных, измененных транзакцией в течение 1 с.В качестве примера возьмем mysql5.7.23, по умолчанию 16M.
mysql> show variables like '%innodb_log_buffer_size%';
+------------------------+----------+
| Variable_name | Value |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
Для большинства приложений достаточно буфера размером 16 М. Стратегии синхронизации буфера с журналом повторов следующие:
- Главный поток каждую секунду сбрасывает буфер в журнал повторов.
- Когда каждая транзакция фиксируется, буфер сбрасывается в журнал повторов.
- Когда оставшееся место в буфере меньше 1/2, оно будет сброшено в журнал повторов.
Следует отметить, что процесс сброса буфера журнала повторов в журнал повторов на самом деле не сбрасывает на диск, а только в кеш ОС Это оптимизация, сделанная современными операционными системами для повышения эффективности записи файлов. реальная запись будет решаться самой системой (например, кэш ОС достаточно велик). Тогда есть проблема для InnoDB: если его сдать в систему для fsync, если система выйдет из строя, данные тоже будут потеряны (хотя вероятность того, что вся система упадет, все еще относительно мала). Для этой ситуации InnoDB даетinnodb_flush_log_at_trx_commitПолитика, пусть пользователь решает, какую из них использовать.
mysql> show variables like 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
- 0: указывает, что после фиксации транзакции fsync не выполняется, но мастер выполняет fysnc журнала повторов каждую 1 с.
- 1: значение по умолчанию, fsync выполняется синхронно каждый раз, когда транзакция фиксируется.
- 2: После записи в кеш ОС оставьте операционной системе решать, когда выполнять fsync.
Из трех стратегий чистки:
2Это определенно наиболее эффективно, но пока операционная система не работает, данные в кеше ОС будут потеряны.В этом случае D в ACID не может быть выполнено.
0Если это компромисс, его теория эффективности ввода-вывода выше, чем1, ниже2Да, его теория безопасности данных ниже, чем1, выше чем2Да, в этой стратегии тоже есть риск потери данных и нет гарантии D.
1Это значение по умолчанию, которое может гарантировать D, данные никогда не будут потеряны, но эффективность будет наихудшей. Лично рекомендуется использовать значение по умолчанию.Хотя вероятность простоя операционной системы меньше, чем вероятность простоя базы данных, поскольку обычно используются транзакции, безопасность данных должна быть относительно более важной.
Журнал повторов — это физическая модификация страницы, и x-я позиция x-й страницы изменяется на xx.,Например:
page(2,4),offset 64,value 2
В движке InnoDB журналы повторов хранятся блоками по 512 байт, и каждая единица хранения называется блоком журнала повторов.Если объем журналов, хранящихся на странице, превышает 512 байт, то ее необходимо логически разделить на несколько блоки для хранения.
Блок журнала повторов состоит из заголовка журнала, тела журнала и хвоста журнала. Заголовок журнала занимает 12 байт, а хвост журнала занимает 8 байт, поэтому данные, которые реально может хранить блок, составляют 512-12-8=492 байта.Несколько блоков журнала повторов составляют наш журнал повторов.
Размер каждого журнала повторного выполнения по умолчанию составляет 48 МБ:
mysql> show variables like 'innodb_log_file_size';
+----------------------+----------+
| Variable_name | Value |
+----------------------+----------+
| innodb_log_file_size | 50331648 |
+----------------------+----------+
По умолчанию InnoDB использует два журнала повторного выполнения для формирования группы журналов, и именно эта группа журналов действительно работает.
mysql> show variables like 'innodb_log_files_in_group';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| innodb_log_files_in_group | 2 |
+---------------------------+-------+
#ib_logfile0
#ib_logfile1
При записи ib_logfile0 будет записан ib_logfile1, при записи ib_logfile1 снова будет записан ib_logfile0..., и он будет записан в цикле.
Почему блок рассчитан на 512 байт?
Это связано с сектором диска. Сектор механического диска по умолчанию составляет 512 байт. Если данные, которые вы хотите записать, больше 512 байт, то для записи должно быть более одного сектора. В это время, задействована пластина.Вращайте, чтобы найти следующий сектор, предполагая, что два сектора A и B нужно записать сейчас, если запись сектора A прошла успешно, но запись сектора B не удалась, то будет неатомарная запись, и Если за один раз записывается только 512 байтов того же размера, что и сектор, то каждая запись является атомарной.
Почему двухчастное представление?
Из вышеизложенного мы знаем, что отправка транзакции должна сначала записать журнал повторов (подготовить), затем записать бинлог и, наконец, отправить (фиксировать). Почему здесь есть действие подготовки? Не можете журнал повторов напрямую зафиксировать статус? Предполагая, что журнал повторов отправляется напрямую, при записи бинлога происходит сбой.В это время в бинлоге нет соответствующих данных, тогда все подчиненные устройства, которые полагаются на бинлог для восстановления данных, не имеют соответствующих данных, что приводит к несогласованности между ведущим и раб. Следовательно, необходимо обеспечить согласованность журнала повторов и бинлога посредством двухэтапной (2pc) отправки. Конкретные шаги: журнал повторов в состоянии подготовки запишет XID 2PC, а binlog также запишет XID 2PC после записи, и в то же время журнал повторов будет помечен логотипом фиксации. .
Может ли журнал повторов и журнал bin нужен только один из них?
Не может. Размер самого журнала повторов фиксирован.После его заполнения он начнется заново и перезапишет старые данные.Поскольку журнал повторов не может сохранить все данные, в режиме ведущий-ведомый, если вы хотите синхронизировать данные с подчиненную библиотеку через журнал повторов, нельзя. Тогда обязательно нужен binlog.Binlog генерируется серверным уровнем MySQL и не имеет ничего общего с механизмом хранения.Binlog также называется архивным журналом.Когда файл binlog заполнен, он будет записан в новый файл binlog. Так нам нужен только бинлог? Журнал повторов не нужен? Конечно, нет. Роль журнала повторного выполнения заключается в обеспечении отказоустойчивости. Прежде всего, для модификации данных сначала изменяется страница данных в пуле буферов. В это время измененные данные фактически не помещаются в диск. Это в основном потому, что дискретные возможности чтения и записи диска неэффективны, и реальная работа по размещению диска передается главному потоку для регулярной обработки. Преимущество заключается в том, что мастер может записывать несколько модификаций на диск в одно время. Тогда проблема в это время.При коммите транзакции данные находятся в грязных страницах буфера и еще не сброшены на диск.В это время происходит сбой базы данных,и данные этого коммита восстанавливаются даже после восстановления базы данных.Его нельзя восстановить, и он не может удовлетворить D в ACID, а затем есть журнал повторов.С точки зрения процесса, отправка транзакции должна гарантировать, что журнал повторов будет успешно записан. Только когда журнал повторов успешно записан, транзакция может быть успешно отправлена. В большинстве случаев журнал записывается на диск последовательно, что намного эффективнее. Когда после фиксации происходит сбой, мы можем восстановить данные через журнал повторов, поэтому журнал повторов необходим. Однако для отправки транзакции также требуется успешная запись бинлога, так почему же через бинлог нельзя восстановить данные, которые не были помещены на диск? Это связано с тем, что binlog не знает, какие данные были удалены, поэтому он не знает, какие данные необходимо восстановить. Для журнала повторов данные в соответствующем журнале повторов будут удалены после размещения данных на диске.После перезапуска базы данных необходимо только восстановить оставшиеся данные в журнале повторов.
Как восстановиться после сбоя?
Благодаря двухэтапной отправке мы знаем, что журнал повторов и бинлог будут помечаться с помощью prepare или commit на каждом этапе, а также будет записываться XID транзакции. С этими данными при перезапуске базы данных она пойдет в журнал повторов, чтобы проверить все. Если транзакция журнала повторов находится в состоянии фиксации, это означает, что после фиксации произошел сбой. В это время данные журнала повторов могут быть восстановлены напрямую. находится в состоянии подготовки, значит перед фиксацией произошел сбой.В это время Статус бинлога определяет статус текущей транзакции.Если в бинлоге есть соответствующий XID, значит, бинлог был успешно написано, но еще не отправлено.В это время снова выполнить коммит.Если соответствующий XID не может быть найден в бинлоге, значит бинлог рухнул, если он не был успешно записан, то на этом должен быть выполнен откат время.
undo log
Журнал повторов — это гарантия долговечности транзакций, а журнал отмен — гарантия атомарности транзакций. Предварительная операция обновления данных в транзакции фактически сначала записывается в журнал отмены, поэтому ее процесс выглядит примерно следующим образом:
При каких обстоятельствах будет создан журнал отмены?
Функцией журнала отмен является mvcc (управление несколькими версиями) и откат. В основном мы говорим об откате здесь. Когда мы вставляем, обновляем и удаляем некоторые данные в транзакции, будет сгенерирован соответствующий журнал отката. Когда мы выполняем откат При накате можно вернуться к началу транзакции через журнал отмен. Следует отметить, что откат — это не измененная физическая страница, а логическое восстановление к исходному состоянию, например, данные А, которые были изменены вами на В в транзакции, но в это время другая транзакция изменила их на С , Если откат напрямую изменяет страницу данных и меняет данные на A, то C перезаписывается.
Для механизма InnoDB каждая запись строки имеет несколько скрытых столбцов в дополнение к данным самой записи:
- DB_ROW_ID: если первичный ключ явно не определен для таблицы и в таблице не определен уникальный индекс, то InnoDB автоматически добавит скрытый столбец row_id в качестве первичного ключа для таблицы.
- DB_TRX_ID: Каждой транзакции присваивается идентификатор транзакции.При изменении записи идентификатор транзакции этой транзакции записывается в trx_id.
- DB_ROLL_PTR: Указатель отката, по сути, является указателем на журнал отмен.
Когда мы делаем INSERT:
begin;
INSERT INTO user (name) VALUES ("tom")
Вставленные данные будут генерировать журнал отмены вставки, и указатель отката данных будет указывать на него. Журнал отмены будет записывать серийный номер журнала отмены, столбец и значение, вставленное в первичный ключ..., затем при выполнении отката соответствующие данные могут быть удалены непосредственно через первичный ключ.
Для операции обновления будет создан журнал отмены обновления, и первичный ключ будет обновлен, а первичный ключ не будет обновлен. Предположим, что он выполняется сейчас:
UPDATE user SET name="Sun" WHERE id=1;
В это время старая запись будет записана в новый журнал отмены, а указатель отката будет указывать на новый журнал отмены, его номер отмены равен 1, а новый журнал отмены будет указывать на старый журнал отмены (номер отмены = 0).
Предположим, теперь выполните:
UPDATE user SET id=2 WHERE id=1;
Для операции обновления первичного ключа сначала будет открыта исходная метка удаления данных.В настоящее время реального удаления данных нет.Реальное удаление будет оцениваться потоком очистки, а затем новые данные будут вставлены позже , и новые данные также будут Журнал отмены будет создан, и порядковый номер журнала отмены будет увеличен.
Можно обнаружить, что каждое изменение данных будет генерировать журнал отмены.Когда запись изменяется несколько раз, будет создано несколько журналов отмены.Журнал отмены записывает журнал перед изменением и серийный номер каждого журнала отмены. , то когда мы захотим откатиться, мы сможем найти наши исходные данные, продвинувшись вперед по серийному номеру.
Как выполняется откат журнала отмены?
В приведенном выше примере, предполагая выполнение отката, соответствующий процесс должен быть следующим:
- Удалить данные с id=2 через лог отката no=3
- Восстановите метку удаления данных с id=1 на 0, удалив журнал no=2
- Восстановить имя данных с id=1 для Тома через лог отмены no=1
- Удалить данные с id=1 через лог отката no=0
Где существует журнал отмены?
InnoDB управляет журналом отмены по сегментам, то есть сегментом отката.Каждый сегмент отката записывает 1024 сегмента журнала отмены.Движок InnoDB по умолчанию поддерживает 128 сегментов отката.
mysql> show variables like 'innodb_undo_logs';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| innodb_undo_logs | 128 |
+------------------+-------+
Тогда максимальное количество одновременных транзакций, которое может поддерживаться, составляет 128*1024. Каждый сегмент журнала отмены похож на поддержание массива из 1024 элементов.
Когда мы начинаем транзакцию и нам нужно написать журнал отмены, мы должны перейти к сегменту журнала отмены, чтобы найти свободную позицию.Когда есть вакансия, мы подадим заявку на страницу отмены, и, наконец, мы подадим заявку на страницу отмены. стр. Запишите журнал отмены. Мы знаем, что размер страницы по умолчанию в mysql составляет 16 КБ.
mysql> show variables like '%innodb_page_size%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
Таким образом, выделение страницы для транзакции на самом деле очень расточительно (если только ваша транзакция не очень длинная).Предполагая, что TPS вашего приложения составляет 1000, тогда требуется 1000 страниц в 1 с, около 16 МБ памяти и около 1 минуты. хранилище... Если это будет продолжаться, если MySQL не будет тщательно очищен, со временем дисковое пространство будет расти очень быстро, и много места будет потрачено впустую. Таким образом, страница отмены предназначена для повторного использования. Когда транзакция зафиксирована, страница отмены не будет удалена немедленно. Из-за повторного использования страница отмены может быть грязной, поэтому страница отмены может быть перемешана с журналами отмены другие сделки. После фиксации журнала отмен он будет помещен в связанный список, а затем будет оцениваться, меньше ли используемое пространство страницы отмены 3/4. Если меньше 3/4, это означает, что Текущая страница отмены может быть использована повторно, поэтому она не будет использоваться.Переработка, журнал отмены других транзакций может быть записан за текущей страницей отмены. Поскольку журнал отмен является дискретным, очистка соответствующего дискового пространства не так эффективна.
Подпишитесь на одноименную официальную учетную запись и получайте электронные книги, такие как компьютерная сеть, структура данных, redis, mysql, java, go, python и т. д.