Я исследую несколько возможностей , как выполнить атомарное (и длительное) обновление файла в файловой системе .Я делаю это, потому что я хочу узнать и понять, как это работает в системах баз данных.Некоторые предположения:
- Только один процесс обращается к файлу в любой момент времени (процесс «владеет» файлом).
- Нет одновременных записей, глобальная блокировка чтения / записи навесь файл в порядке.
- Файл является произвольно большим (насколько позволяет файловая система) файлом, содержащим двоичные данные (например, B-дерево).
- Только пользовательская земля (нетРазрешены расширения ядра)
Что я узнал до сих пор:
В основном все операционные системы имеют буфер обратной записи, где онисохраняйте изменения файла до тех пор, пока не будет вызвана fsync()
(или аналогичная команда), которая сбрасывает изменения на диск.
fsync()
само по себе не атомарно , в частностиесли задействовано несколько страниц памяти.
fsync()
- довольно дорогая операция, слишком дорогая для вызова при каждом коммите.
Базы данных сохраняютсяжурнал записи вперед (WAL), в котором хранятся все входящие транзакции.Через определенные интервалы (размер файла WAL, или таймер или ...) изменения применяются и fsync()
ed.
Все изменения в WAL необходимо учитывать при выполнении запросов,как будто эти изменения уже были частью основного файла.Поскольку это может стать медленным, когда WAL становится больше (он не индексируется), желательно очищать WAL заранее.Похоже, существует компромисс между стоимостью большого файла WAL и стоимостью сброса изменений в основной файл.
Поскольку fsync()
может закончить запись половинысо страницы на диск (например, в случае потери питания), все страницы памяти, затронутые транзакциями в WAL, необходимо также скопировать в WAL, чтобы эти страницы можно было восстановить при перезагрузке системы.После успешного возврата команды fsync()
мы можем удалить записи из WAL.
Мои вопросы:
Правильно ли я понял это до сих пор?
Изменяется ли что-либо из вышеперечисленного при использовании mmap
файлов ed вместо обычных файлов?
На мой взгляд, все это на самом деле не «решает» проблему, а лишь снижает вероятность коррупции.В конце концов, сам WAL - это файл, который должен быть fsync()
ed, что может привести к сбою.Является ли fsync()
в WAL "дешевле", чем fsync()
в нашем файле данных?
Выполняем ли мы fsync()
непосредственно после каждого коммита?Даже высокопроизводительные системы баз данных, такие как PostGreSQL , периодически делают это , что лично меня очень беспокоит.Разве мы не рискуем полностью потерять коммит, если машина выключится до того, как мы fsync()
отредактируем файл WAL?
Как защитить наш файл WAL от повреждения данных из-занеполная синхронизация страниц?WAL для WAL?
Любые ссылки на учебные ресурсы по этому вопросу (кроме "прочитать исходный код базы данных XY") также будут высоко оценены.