RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
Visa 
4274 3200 2453 6495 

Small. Fast. Reliable.
Choose any three.

Этот документ описывает детали низкого уровня о том, как режим WAL работает в unix и windows.

Отдельный формат файла предоставляет подробную информацию о структуре файла базы данных и файла журнала записи, используемого в режиме WAL. Но детали протокола блокировки и формата WAL-индекса сознательно опущены, так как те детали оставляют усмотрению отдельных внедрений VFS. Этот документ заполняет пропущенные детали для Unix и windows VFS.

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

1. Файлы на диске

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

  1. Главный файл базы данных с произвольным именем "X".
  2. Файл журнала с упреждающей записью обычно названный "X-wal".
  3. Файл wal-index обычно названный "X-shm".

1.1. Главный файл базы данных

Формат главного файла базы данных описан в документе file format. Номера версий формата файла по адресам 18 и 19 в главной базе данных должны оба быть 2, чтобы указать, что база данных находится в режиме WAL. Главная база данных имеет произвольное имя. Никакие специальные суффиксы файла не требуются, хотя ".db", ".sqlite" и ".sqlite3", кажется, популярный выбор.

1.2. Журнал с упреждающей записью или файл "-wal"

Журнал с упреждающей записью или файл "-wal" это журнал наката, который делает запись транзакций, которые передавались, но еще не применились к главной базе данных. Детали о формате wal-файла описывают в подразделе WAL format описания формата файла. wal-файл называют, прилагая эти четыре знака "-wal" к концу названия главного файла базы данных. За исключением 8+3 файловых систем, где не позволены такие имена, в этом случае суффикс файла изменяется на ".WAL". Но поскольку 8+3 файловых системы все более и более редки, этот исключительный случай может обычно игнорироваться.

1.3. Wal-Index или файл "-shm"

Wal-Index или файл "-shm" на самом деле не используется в качестве файла. Скорее отдельные клиенты базы данных отображают файл shm и используют это как общую память для координирования доступа к базе данных и как кэш для того, чтобы быстро определить местонахождение структуры в wal-файле. Название файла shm это главное имя файла базы данных с этими четырьмя знаками "-shm". Или для 8+3 файловых систем файл это главный файл базы данных с суффиксом, измененным на ".SHM".

shm не содержит содержания базы данных и не требуется, чтобы восстановить базу данных после катастрофы. По этой причине первый клиент, который соединится с базой данных, будет обычно усекать файл shm, если он будет существовать. Так как содержание файла shm не должно быть сохранено после сбоя, он никогда не fsync() на диск. На самом деле, если бы был механизм, которым SQLite мог сказать операционной системе никогда не сохранять файл shm на диск, а всегда держать его в кэш-памяти, то SQLite использовал бы этот механизм, чтобы избежать любого ненужного дискового I/O, связанного с этим файлом. Однако, никакой такой механизм не существует в стандарте posix.

Поскольку shm используется только, чтобы скоординировать доступ между параллельными клиентами, файл shm опущен, если установлен exclusive locking mode. Когда exclusive locking mode установлен, SQLite использует память кучи вместо файла shm с отображенной памятью.

1.4. Жизненные циклы файла

Когда база данных WAL в активном употреблении, все три из вышеупомянутых файлов обычно существуют. Wal-Index опущен, если установлен exclusive locking mode.

Если последний клиент, использующий базу данных, закрывается чисто, вызывая sqlite3_close(), то контрольной точкой управляют автоматически, чтобы передать всю информацию от wal-файла в главную базу данных, файл shm и файл wal расцепляются. Таким образом, когда база данных не используется никаким клиентом, обычно имеет место, что только главный файл базы данных существует на диске. Однако, если последний клиент не вызвал sqlite3_close() прежде чем он закрылся, или если последний клиент был клиентом только для чтения, то заключительная операция очистки не происходит и файлы shm и wal могут все еще существовать на диске, даже когда база данных не используется.

1.5. Изменения

Когда PRAGMA locking_mode=EXCLUSIVE (установлен exclusive locking mode), только единственному клиенту разрешают иметь базу данных, открытую когда-то. Так как только единственный клиент может использовать базу данных, файл shm опущен. Единственный клиент использует буфер в памяти кучи вместо файла shm.

Если клиент чтения-записи вызывает sqlite3_file_control( SQLITE_FCNTL_PERSIST_WAL) до закрытия, то при закрытии контрольной точкой все еще управляют, но файлы shm и wal не удалены. Это позволяет последующим клиентам только для чтения соединяться и читать базу данных.

2. Формат файла WAL-Index

WAL-index или "shm" используется, чтобы скоординировать доступ к базе данных многократными клиентами, и как кэш, чтобы помочь клиентам быстро определить местонахождение структур в wal-файле.

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

Файл shm состоит из одной или более хэш-таблиц, где каждая хэш-таблица составляет 32768 байтов в размере. Кроме того, 136-байтовый заголовок вырезан из самой первой хэш-таблицы, таким образом, первая хэш-таблица составляет только 32632 байта в размере. Полный размер файла shm всегда кратен 32768. В большинстве случаев полный размер файла shm точно 32768 байтов. Файл shm должен вырасти вне единственной хэш-таблицы только когда wal-файл становится очень большим (больше 4079 структур). Начиная с умолчания автоматического порога контрольной точки 1000, файлы WAL редко достигают 4079.

2.1. Заголовок WAL-Index

Первые 136 байтов файла shm это заголовок. У заголовка shm есть три главных раздела:

Разделы заголовка WAL-Index
БайтыОписание
0..47Первая копия WAL Index
48..95Вторая копия WAL Index
96..135 Информация о контрольной точке и блокировках

Отдельные области заголовка shm, за исключением значений salt, скопированных с заголовка WAL, являются целыми без знака в родном порядке байтов хост-машины. Значения salt это точные копии от заголовка WAL и находятся в любом порядке байтов, который используется файлом WAL. Размер целых чисел может быть 8, 16, 32 или 64 бита. Значение отдельных областей заголовка shm:

Детали заголовка WAL-Index
БайтыИмяСмысл
0..3iVersion Номер версии формата WAL-индекса. Всегда 3007000.
4..7  Неиспользованное пространство дополнения. Должен быть ноль.
8..11iChange Счетчик Unsigned integer, растет с каждой транзакцией.
12isInit Флаг "isInit". 1, когда файл shm был инициализирован.
13bigEndCksum True,если файл WAL использует контрольные суммы big-ending. 0 иначе.
14..15szPage Размер страницы базы данных в байтах или 1, если размер страницы 65536.
16..19mxFrame Количество действительных и переданных структур в файле WAL.
20..23nPage Размер файла базы данных в страницах.
24..31aFrameCksum Контрольная сумма последней структуры в файле WAL.
32..39aSalt Два значения salt, скопированных с заголовка файла WAL. Эти значения в порядке байтов файла WAL, который мог бы отличаться от родного порядка байтов машины.
40..47aCksum Контрольная сумма байтов 0-39 заголовка.
48..95  Контрольная сумма байтов 0-47 заголовка.
96..99nBackfill Количество структур WAL, которые были уже заделаны в базу данных предшествующими контрольными точками.
100..119read-mark[0..4] Пять "прочитанных отметок". Каждая прочитанная отметка это 32-битное целое без знака (4 байта).
120..127  Неиспользуемое место отложено для 8 блокировок файла.
128..132nBackfillAttempted Количество структур WAL, которые попытались быть заделанными, но которые, возможно, не были заделаны успешно.
132..136  Неиспользуемое место зарезервировано для дальнейшего расширения.

2.1.1. Поле mxFrame

32-bit unsigned integer по адресу 16 (повторен по адресу 64) это количество действительных структур в WAL. Поскольку структуры WAL пронумерованы с 1, mxFrame это также индекс последней действительной переданной структуры в WAL. Переданная структура это структура, у которой есть ненулевое значение "size of database" в байтах 4-7 заголовка структуры и это указывает на конец транзакции.

Когда mxFrame = 0, это указывает, что WAL пуст и что все содержание должно быть получено непосредственно из файла базы данных.

Когда mxFrame = nBackfill, это указывает, что все содержание в WAL было написано в ответ в базу данных. В этом случае все содержание может быть прочитано непосредственно из базы данных. Кроме того, следующий писатель свободен перезапустить WAL, если никакие другие связи не держат блокировки WAL_READ_LOCK(N) для N>0.

mxFrame всегда больше или равно nBackfill и nBackfillAttempted.

2.1.2. Поле nBackfill

32-bit unsigned integer по адресу 128 в заголовке WAL-index это "nBackfill". Эта область содержит количество структур в файле WAL, которые были скопированы назад в главную базу данных.

nBackfill никогда не больше mxFrame. Когда nBackfill = mxFrame, это означает, что содержание WAL было полностью написано в ответ в базу данных и нормально можно перезапустить WAL, нет блокировок на любом WAL_READ_LOCK(N) для N>0.

nBackfill может быть увеличен только, держа WAL_CKPT_LOCK. Однако, nBackfill изменяется на ноль во время WAL reset и это происходит, держа WAL_WRITE_LOCK.

2.1.3. Блокировки WAL

Восемь байтов обойдены в заголовке для поддержки блокировки файла, используя метод xShmLock() объекта sqlite3_io_methods. Эти восемь байтов никогда не читаются и не пишутся SQLite, начиная с некоторого VFS (кроме Windows).

Это восемь поддержанных блокировок:

Блокировки WAL-Index, управляемые xShmLock()
ИмяСмещение
xShmLock
WAL_WRITE_LOCK0120
WAL_CKPT_LOCK1121
WAL_RECOVER_LOCK2122
WAL_READ_LOCK(0)3123
WAL_READ_LOCK(1)4124
WAL_READ_LOCK(2)5125
WAL_READ_LOCK(3)6126
WAL_READ_LOCK(4)7127

2.2. Хэш-таблицы WAL-Index

Хэш-таблицы в файле shm разработаны, чтобы ответить на следующий вопрос быстро:

FindFrame(P,M): Учитывая номер страницы P и максимальный индекс M структуры WAL, возвратите самый большой индекс структуры WAL для страницы P, который не превышает M, или NULL при отсутствии структур для страницы P, которые не превышают M.

Допустим, что типы "u8", "u16" и "u32" это unsigned integer длиной 8, 16 и 32 бит, соответственно. Первая 32768-байтовая единица файла shm организована следующим образом:

u8 aWalIndexHeader[136];
u32 aPgno[4062];
u16 aHash[8192];

Вторая и все последующие 32768-байтовые единицы файла shm похожи на это:

u32 aPgno[4096];
u16 aHash[8192];

Коллективно, записи aPgno делают запись номера страницы базы данных, сохраненного во всех структурах файла WAL. Вход aPgno[0] в первой хэш-таблице делает запись номера страницы базы данных, сохраненного в самой первой структуре в файле WAL. aPgno[i] из первой хэш-таблицы является номером страницы базы данных для i-й структуры в файле WAL. Вход aPgno[k] для второй хэш-таблицы это номер страницы базы данных для (k+4062)-й структуры в файле WAL. Вход aPgno[k] для n-й 32768-байтной хэш-таблицы в файле shm (для n>1) считает номер страницы базы данных сохраненным в (k+4062+4096*(n-2))-м фрейме файла WAL.

Вот немного отличающийся способ описать значения aPgno: если вы думаете обо всех значениях aPgno как о смежном множестве, то номер страницы базы данных, сохраненный в i-й структуре файла WAL, сохранен в aPgno[i]. Конечно, aPgno не смежное множество. Первые 4062 записей находятся в первой 32768-байтовой единице файла shm, и последующие значения находятся в кусках по 4096 входа в более поздних единицах файла shm.

Один способ вычислить FindFrame (P, M) состоял бы в том, чтобы просмотреть множество aPgno, начинающееся с входа M, работать назад к началу и возвратить J, где aPgno[J]==P. Такой алгоритм работал бы, и это будет быстрее, чем поиск целого файла WAL для последней структуры с номером страницы P. Но поиск может быть сделан намного быстрее при помощи структуры aHash.

Номер страницы P базы данных отображен в значение хэш-функции, используя следующую хеш-функцию:

h = (P * 383)%8192

Эта функция отображает каждый номер страницы в целое число между 0 и 8191 включительно. Поле aHash каждой 32768-байтовой единицы файла shm отображает значения P в индексы поля aPgno той же самой единицы следующим образом:

  1. Вычислите значение хэш-функции: h = P * 383.
  2. Допустим, X это самый большой набор последовательных целых чисел {h, h+1, h+2..., h+N}, таким образом для каждого j в X, aPgno[j%8192]!=0. Эти X будут пусты, если aPgno[h%8192]==0. Наборы X легко вычисляются, начиная со значения h%8192, и добавляя h%8192 к X и увеличивая h до столкновения с первым входом aPgno[h%8192] = 0.
  3. Набор X содержит индекс в aPgno каждого входа в текущей 32768-байтовой единице файла shm, который мог бы быть решением функции FindFrame(P,M). Каждые из этих записей должны быть проверены отдельно, чтобы гарантировать, что значение aPgno это P и что номер структуры не превышает M. Самое большое количество структуры, которое проходит те два теста, является ответом.

У каждого входа во множестве aPgno есть единственный соответствующий вход во множестве aHash. Есть более доступные места в aHash, чем есть в aPgno. Неиспользуемые слоты в aHash заполнены нолем. И с тех пор там, как гарантируют, будут неиспользуемыми слотами в aHash, это означает, что цикл, который вычисляет X, закончится. Ожидаемый размер X является меньше 2. Худший случай это то, что X совпадет с количеством записей в aPgno, в этом случае алгоритма работает на приблизительно той же самой скорости, как линейный просмотр aPgno. Но это редко. Обычно размер X будет небольшим и использование множества aHash позволяет вычислять FindFrame(P,M) намного быстрее.

Вот альтернативный способ описать алгоритм поиска хэша: начните с h = (P * 383)%8192 и посмотрите на aHash[h] и последующие записи, когда h достигнет 8192 до нахождения входа с aHash[h] == 0. У всех записей aPgno, имеющих номер страницы P, будет индекс, который является одним из значений aHash[h], таким образом вычисленных. Но не все вычисленные значения aHash[h] будет соответствовать соответствующим критериям, таким образом, необходимо проверить их независимо. Преимущество скорости появляется, потому что обычно этот набор значений h очень маленький.

Обратите внимание на то, что у каждой 32768-байтовой единицы файла shm есть свой собственный aHash и множество aPgno. Множество aHash для единого блока полезно только в нахождении записи aPgno в той же самой единице. Функция FindFrame(P,M) должна сделать поиски хэша, начинающиеся с последней единицы и работающие назад к самой старой единице, пока это не находит ответ.

2.3. Блокировка матрицы

Доступ скоординирован в режиме WAL, используя и устаревшие блокировки DELETE, которыми управляют методы xLock и xUnlock объекта sqlite3_io_methods, и блокировки WAL, которыми управляет метод xShmLock объекта sqlite3_io_methods.

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

  1. SQLITE_LOCK_NONE (разблокировано)
  2. SQLITE_LOCK_SHARED (чтение)
  3. SQLITE_LOCK_RESERVED (чтение, ожидается запись)
  4. SQLITE_LOCK_PENDING (новые читатели заблокированы, ожидая запись)
  5. SQLITE_LOCK_EXCLUSIVE (запись)

Блокировка DELETE сохранена в странице блокировок главного файла базы данных. Только SQLITE_LOCK_SHARED и SQLITE_LOCK_EXCLUSIVE это факторы для баз данных WAL. Другие состояния блокировки используются в режиме обратной перемотки, но не в WAL.

2.3.1. Как различные блокировки используются

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

  • SQLITE_LOCK_SHARED

    Все связи держат SQLITE_LOCK_SHARED непрерывно в то время, как подключены к базе данных WAL. Это верно для связей чтения-записи и для связей только для чтения. SQLITE_LOCK_SHARED проводится даже связями, которые не в транзакции. Это отличается от способа обратной перемотки, где SQLITE_LOCK_SHARED снята в конце каждой транзакции.

  • SQLITE_LOCK_EXCLUSIVE

    Связи держат монопольную блокировку, когда переключаются между WAL и любым режимом обратной перемотки. Связи могли бы также попытаться получить блокировку EXCLUSIVE, когда они отсоединяются от режима WAL. Если связь в состоянии получить блокировку EXCLUSIVE, это означает, что это единственная связь с базой данных и таким образом, это может попытаться перейти к контрольной точке и затем удалить WAL-индекс и файлы WAL.

    Когда связь держит блокировку SHARED на главной базе данных, это будет препятствовать тому, чтобы любая другая связь приобрела блокировку exclusive, которая в свою очередь препятствует тому, чтобы WAL-индекс и файлы WAL были удалены из-под других пользователей и предотвращает выход из режима WAL в то время, как другие пользователи получают доступ к базе данных в режиме WAL.

  • WAL_WRITE_LOCK

    WAL_WRITE_LOCK только исключительная блокировка. Никогда нет коллективной блокировки, взятой WAL_WRITE_LOCK.

    EXCLUSIVE WAL_WRITE_LOCK проводится любой связью, которая прилагает содержание к концу WAL. Следовательно, только единственный процесс за один раз может приложить содержание к WAL. Если перезапуск WAL происходит в результате записи, то поле nBackfill заголовка WAL-index перезагружается к нолю, держа эту блокировку.

    EXCLUSIVE также держит WAL_WRITE_LOCK и на нескольких других байтах блокировки, когда связь управляет восстановлением на общем WAL-индексе.

  • WAL_CKPT_LOCK

    WAL_CKPT_LOCK только исключительная блокировка. Никогда нет коллективной блокировки, взятой WAL_CKPT_LOCK.

    EXCLUSIVE WAL_CKPT_LOCK проводится любой связью, которая управляет контрольной точкой. Поле nBackfill заголовка WAL-index может быть увеличено, держа эту монопольную блокировку, но это не может быть уменьшено.

    EXCLUSIVE также держит WAL_CKPT_LOCK и на нескольких других байтах блокировки, когда связь управляет восстановлением на общем WAL-индексе.

  • WAL_RECOVER_LOCK

    WAL_RECOVER_LOCK только исключительная блокировка. Никогда нет коллективной блокировки, взятой WAL_RECOVER_LOCK.

    EXCLUSIVE WAL_RECOVER_LOCK проводится любой связью, которая управляет восстановлением, чтобы восстановить общий WAL-индекс.

    Связь только для чтения, которая восстанавливает ее частный WAL-индекс памяти кучи, не держит эту блокировку. Это не может ее получить, так как связям только для чтения не позволяют держать монопольные блокировки. Эта блокировка проводится только восстанавливая глобальный общий WAL-индекс, содержавшийся в файле SHM с отображенной памятью.

    В дополнение к блокировке этого байта связь, выполняющая восстановление, также получает монопольную блокировку на всех других блокировках WAL кроме WAL_READ_LOCK(0).

  • WAL_READ_LOCK(N)

    Есть пять отдельных блокировок чтения с номерами от 0 до 4. Они могут быть SHARED или EXCLUSIVE. Связи получают коллективную блокировку на одном из байтов блокировки чтения в то время, как они в транзакции. Связи также получают монопольную блокировку на блокировках чтения, по одной, в течение краткого момента в то время, как они обновляют значения соответствующих прочитанных отметок. Блокировки чтения 1-4 проводятся исключительно когда выполняется восстановление.

    Каждый байт блокировки чтения соответствует одному из пяти 32-битных integer прочитанной отметки, расположенных в байтах 100-119 заголовка WAL-индекса, следующим образом:

    Имя блокировкиСмещение блокировки Имя прочитанной отметкиСмещение прочитанной отметки
    WAL_READ_LOCK(0)123read-mark[0] 100..103
    WAL_READ_LOCK(1)124read-mark[1] 104..107
    WAL_READ_LOCK(2)125read-mark[2] 108..111
    WAL_READ_LOCK(3)126read-mark[3] 112..115
    WAL_READ_LOCK(4)127read-mark[4] 116..119

    Когда связь держит коллективную блокировку на WAL_READ_LOCK(N), которая является обещанием связи, что это будет использовать WAL, а не файл базы данных для любых страниц базы данных, которые изменяются первой прочитанной отметкой read-mark[N] в WAL. read-mark[0] всегда 0. Если связь держит коллективную блокировку на WAL_READ_LOCK(0), это означает, что связь ожидает быть в состоянии проигнорировать WAL и прочитать любое содержание от главной базы данных. Если N>0, связь может использовать больше файла WAL вне read-mark[N], если хочет, до первых структур mxFrame. Но когда связь держит коллективную блокировку на WAL_READ_LOCK(0), это является обещанием, что это никогда не будет читать содержание от WAL и приобретет все содержание непосредственно от главной базы данных.

    Когда контрольная точка работает, если она видит блокировку на WAL_READ_LOCK(N), она не должна перемещать содержание WAL в главную базу данных для больше, чем N первых структур read-mark[N]. Если сделать так, это перепишет содержание, которое процесс, держащий блокировку, ожидал быть в состоянии прочитать из главного файла базы данных. Последствие этого, если файл WAL f содержит больше, чем read-mark[N] структур (если mxFrame>read-mark[N] для любой read-mark, для которой WAL_READ_LOCK(N) проводится другим процессом), тогда контрольная точка не может завершиться.

    Когда писатель хочет перезагрузить WAL, он должен гарантировать, что нет блокировок WAL_READ_LOCK(N) для N>0 потому что такие блокировки указывают, что некоторая другая связь все еще использует текущий файл WAL, и перезапуск WAL удалил бы содержание из тех других связей. Для перезапуска WAL нормально происходить, если другие связи держат WAL_READ_LOCK(0) потому что, держа WAL_READ_LOCK(0), те другие связи обещают не использовать любое содержание от WAL.

2.3.2. Операции, которые требуют блокировок

  • Переход в и из WAL-режима

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

  • Закройте связь с базой данных WAL

    Когда соединение с базой данных закрывается (через sqlite3_close() или sqlite3_close_v2()), попытка предпринята, чтобы приобрести SQLITE_LOCK_EXCLUSIVE. Если эта попытка успешна, это означает, что связь, которая закрывается, это последняя связь с базой данных. В этом случае желательно очистить файлы WAL и WAL-индекс, таким образом, заключительная связь управляет контрольной точкой (держа SQLITE_LOCK_EXCLUSIVE) и удаляет файлы WAL и WAL-index. SQLITE_LOCK_EXCLUSIVE не выпущена до окончания удаления файлов WAL и WAL-index.

    Если применение вызывает sqlite3_file_control( SQLITE_FCNTL_PERSIST_WAL) на соединение с базой данных до закрытия, то заключительной контрольной точкой все еще управляют, но WAL и WAL-индекс не удалены. Это оставляет базу данных в состоянии , которое позволяет другим процессам без права записи на базе данных, WAL или WAL-индексе открыть базу данных только для чтения. Если WAL и WAL-индекс будут отсутствовать, то процесс, который испытывает недостаток в разрешении создать и инициализировать те файлы, не будет в состоянии открыть базу данных, если база данных не будет определяться как неизменная через использование without write permission on the database, WAL, or WAL-index files неизменного параметра запроса.

  • Восстановите глобальный общий WAL-индекс во время восстановления.

    Все блокировки WAL-индекса, за исключением WAL_READ_LOCK(0), проводятся исключительно, восстанавливая глобальный общий WAL-индекс во время восстановления.

  • Добавьте новую транзакцию до конца WAL

    Монопольная блокировка держится на WAL_WRITE_LOCK, добавляя новую структуру в конец файла WAL.

  • Прочитайте содержание от базы данных и WAL как часть транзакции.

  • Управляйте контрольной точкой.

  • Перезагрузите файл WAL.

    Перезапуск WAL означает перемотать WAL и начать добавлять новые структуры в начало. Это происходит, прилагая новые структуры к WAL, у которого mxFrame = nBackfill и который не имеет блокировок на WAL_READ_LOCK(1)-WAL_READ_LOCK(4). WAL_WRITE_LOCK проводится.

3. Восстановление

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

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

Если WAL-индекс осуществляется как файл с отображенной памятью, и тот файл только для чтения к первому потоку, то этот поток создает частную память кучи WAL-индекса и управляет режимом восстановления, чтобы наполнить тот частный WAL-индекс.

Восстановление работает, делая единственный проход по WAL с начала до конца. Контрольные суммы проверяются на каждой структуре WAL, когда это прочитано. Просмотр останавливается в конце файла или в первой недействительной контрольной сумме. Поле mxFrame установлена в индекс последней действительной переданной структуры в WAL. Так как номера структур WAL внесены в указатель, начиная с 1, mxFrame также количество действительных структур в WAL. "commit frame" это структура, у которой есть ненулевое значение в байтах 4-7 заголовка структуры. Так как у процедуры восстановления нет способа знать, сколько структур WAL, возможно, было ранее скопировано назад в базу данных, это инициализирует значение nBackfill=0.

Во время восстановления глобального WAL-индекса общей памяти монопольные блокировки держатся на WAL_WRITE_LOCK, WAL_CKPT_LOCK, WAL_RECOVER_LOCK и WAL_READ_LOCK(1)-WAL_READ_LOCK(4). Другими словами, все блокировки, связанные с WAL-индексом за исключением WAL_READ_LOCK(0), проводятся исключительно. Это препятствует тому, чтобы любой другой поток писал базу данных и от чтения любых транзакций, которые проводятся в WAL, пока восстановление не завершено.