Комментарии 8
Можете показать статьи или репорты об утере данных из-за fsynс, который не сохранил данные на диск?
Вообще-то похоже что автор еще собрался решать проблемы fsync репликацией. Ну, у него так написано. А это точно работает? Ну в смысле, если fsync реально может не сохранить данные, и мы их потеряем — с какой стати два fsync на разных машинах нам что-то гарантируют? В лучшем случае — они повысят вероятность. Не до 100%.
да это известный факт. например, из blog.httrack.com/blog/2013/11/15/everything-you-always-wanted-to-know-about-fsync
* Linux/ext3: If the underlying hard disk has write caching enabled, then the data may not really be on permanent storage when fsync() return
* Linux/ext4: The fsync() implementations in older kernels and lesser used filesystems does not know how to flush disk caches
* OSX: For applications that require tighter guarantees about the integrity of their data, Mac OS X provides the F_FULLFSYNC fcntl. The F_FULLFSYNC fcntl asks the drive to flush all buffered data to permanent storage

то есть, есть детали, но это не магические недостатки fsync-а, а баги, которые надо исправлять (использовать F_FULLFSYNC, чинить ext4, кстати, уже починили, и так далее). Всё как обычно, баги случаются.
Спасибо за статью, есть вопросы про durability.

энергозависимый буффер. Время пребывания в нем мало, но не равно 0.

Если диск не игнорирует flush, то есть ли разница, сколько времени, сколько времени данные лежат в кэше записи? К концу flush всё, что надо, будет записано. А если игнорирует, то такие диски противоказано использовать с СУБД.

Как следствие, если выключить электричество ровно в «нужный» момент, то транзакция все-таки может быть потеряна!

Если под «нужным моментом» подразумевается промежуток выполнения flush, то не важно, запишутся данные физически или нет? СУБД не дождётся окончания fsync, транзакция не будет считаться завершённой, и после восстановления при включении питания эти изменения физически откатятся.

Как мне видится, те тактики, которые применяют СУБД для durability (WAL, Checkpoint), достаточны для достижения этой характеристики.
Подробнее про них можно прочитать в статье на Хабре
Как устроены базы данных

Уточню, что мой опыт тестирования durability в нормальных условиях (когда не сдыхает железо) доказывают, что в Postgresql как раз всё отлично. Всё, что БД возвращает сразу после commit, доступно также при восстановлении после сбоя. И после сбоя не появляется ничего лишнего, чего СУБД не вернула после commit.
Попробую догадаться какую проблему скорее всего имел ввиду автор. Дело в том, что применение самого commit-а, на низком уровне, может состоять из нескольких flush() в разрозненных областях диска. Порядок этих flush для логики commit-а — важен. Например: сначала мы обновляем новый служебный блок, делаем ему flush(), потом меняем индекс блока в B-дереве и делаем окончательный flush() в какой-нибудь таблице. Каждый flush() может вернуть управление прежде чем контроллер запишет свои буфера физически на диск. И вот тут тонкость — при нормальной работе (в том числе закрытия процесса) логический порядок всегда правильный, т.е. если читать данные, изменения увидятся в правильном порядке, но вот если произойдет сбой по питанию — здесь все очень сильно будет зависеть от порядка сброса энергонезависимых буферов контроллера. В каком порядке будет запись и будет ли записана вся очередь не смежных блоков в этом случае, это вопрос. Понятно что для обеспечения 100% durability порядок должен строго сохраняться. Все это усложняется ситуацией когда мы имеем сложные слои и комбинации дисковых носителей, разные файловые системы или RAID.

Спасибо за ответ. В общем случае это действительно так. Не читав исходники, не знаешь на 100%, но логично во время commit не делать fsync нигде, кроме wal. А он строго с последовательной записью. За консистентный перенос данных в файлы таблиц Postgresql отвечает checkpoint, он уже может как угодно сложно делать свою работу, чтобы любые прерывания на полпути были обратимыми после аварии.

С логом проще, хотя и там порядок записи блоков очень важен. Я рассматриваю стадию накатывания изменений непосредственно самой базы, например из того же лога. Не очень представляю как алгоритмически можно поменять сложную древовидную структуру за один flush(). Durability возможна, безусловно, но важно что она зависит не только от алгоритмов и API применяемых самой базой данных. Важно, еще, на какой системной конфигурации и на каком оборудовании все это развертывается, и вот тут могут быть нюансы.
Ок, давайте фантазировать, как происходит checkpoint.
1) пишет в wal, что checkpoint начался, и делает fsync
2) копирует изменения, которые произошли с момента последнего checkpoint, в файлы баз данных. Часть этой работы уже сделали ранее другие процессы (напр. bgwriter или сами воркеры запросов).
3) в каком-то порядке делает fsync к файлам базы и дожидается окончания fsync.
4) пишёт в wal номер транзакции начала шага №3 и факт окончания checkpoin, делает fsync.
Следующий chechpoint будет работать с изменениями с момента только что записанного номера транзакции.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.