Возможно ли реализовать ведение журнала с помощью одного fsync на коммит?
Допустим, вы создаете систему хранения журналирования / записи с опережением записи. Можете ли вы просто реализовать это путем (для каждой транзакции) добавления данных (с помощью write(2)), добавления маркера фиксации и затем fsync-ing?
Сценарий, который необходимо рассмотреть, - если вы выполняете большой набор записей в этот журнал, затем выполняете fsync, и во время fsync происходит сбой. Прямые / косвенные указатели блоков inode сбрасываются только после того, как сброшены все блоки данных, или нет никаких гарантий, что блоки очищаются по порядку? Если последнее, то во время восстановления, если вы видите маркер фиксации в конце файла, вы не можете поверить, что данные между ним и маркером предыдущего фиксации имеют смысл. Таким образом, вы должны полагаться на другой механизм (включающий, по крайней мере, другой fsync), чтобы определить, какой размер файла журнала является согласованным (например, запись /fsyncing данных, затем запись /fsyncing маркера фиксации).
Если это имеет значение, в основном, интересно, как ext3/ext4 в качестве контекста.
2 ответа
Обратите внимание, что fuxync и fdatasync в linux и mac os по умолчанию некорректны. Windows верна по умолчанию, но может эмулировать linux для целей тестирования.
Кроме того, fdatasync выдает несколько операций записи на диск, если вы добавляете в конец файла, поскольку ему необходимо обновить inode файла с новой длиной. Если вы хотите иметь одну запись для каждого коммита, лучше всего заранее выделить место в журнале, сохранить CRC записей журнала в маркере фиксации и выполнить одну функцию fdatasync() при фиксации. Таким образом, независимо от того, как сильно переупорядочивается ОС / аппаратное обеспечение за вашей спиной, вы можете найти префикс журнала, который фактически ударил по диску.
Если вы хотите использовать журнал для длительных фиксаций или писать заранее, все становится сложнее, так как вам нужно убедиться, что fsync действительно работает. В Linux вы захотите отключить кэш записи диска с помощью hdparm или смонтировать раздел с установленным в true барьером. [Редактировать: Я исправлен, барьер, кажется, не дает правильную семантику. SATA и SCSI вводят ряд примитивов, таких как барьеры записи и собственные очереди команд, которые позволяют операционным системам экспортировать примитивы, которые позволяют вести запись с опережением записи. Судя по тому, что я могу сказать по man-страницам и в Интернете, Linux предоставляет их только разработчикам файловых систем, а не пользователям.]
Как это ни парадоксально, отключение кэша записи на диск иногда приводит к повышению производительности, поскольку вы получаете больший контроль над планированием записи в пространстве пользователя; если диск ставит в очередь кучу синхронных запросов на запись, вы в конечном итоге подвергаете приложение странным скачкам задержки. Отключение кэша записи предотвращает это.
Наконец, реальные системы используют групповую фиксацию и выполняют < 1 синхронную запись на коммит с одновременными рабочими нагрузками.
Там нет никакой гарантии на порядок, в котором блоки записываются на диск. В наши дни даже сам привод может переупорядочивать блоки по пути к пластинам.
Если вы хотите обеспечить порядок, вы должны по крайней мере fdatasync()
между записками, которые вы хотите заказать. Все обещания синхронизации состоят в том, что при возврате все, что написано до синхронизации, попадет в хранилище.