LINUX.ORG.RU

Целостность файла после записи

 , ,


1

2

Как гарантировать, что текстовый файл не побьется при записи, в случае hard reset/poweroff/kernel panic/т.д.?

Гарантирует ли тоже самое какая-нибудь библиотека для работы с банками данных (типа SQLite)?

Какая файловая система устойчива к таким случаям. Встречал, что с ZFS под Linux были проблемы.

★★★★★

Как гарантировать, что текстовый файл не побьется при записи, в случае hard reset/poweroff/kernel panic/т.д.?

Использовать файловые системы с полным журналированием (ext4 -o data=journal, btrfs -o flushoncommit), использовать атомарные техники работы с файлами (write+fsync+rename).

Гарантирует ли тоже самое какая-нибудь библиотека для работы с банками данных (типа SQLite)?

Да, иначе в них не было бы смысла.

intelfx ★★★★★
()

В общем случае - никак. Хотя бы потому, что хостер использует writeback и держит «горячие» данные в оперативной памяти без фактической записи на диск.

izzholtik ★★★
()

Какая файловая система устойчива к таким случаям. Встречал, что с ZFS под Linux были проблемы

У linux постоянно проблемы, у zfs проблем нет (в данном вопросе)

Lordwind ★★★★★
()

Предполагаю, что подгадить может носитель данных. ОС все сбросила на диск и думает что всё хорошо, а в носителе есть свой кеш данных, который ещё не сброшен. Но как точно обстоят дела с этим делом в реальных устройствах, я не знаю.

pathfinder ★★★★
()
Ответ на: комментарий от intelfx

Использовать файловые системы с полным журналированием

Смотря на какой носитель пишем. Если это какая-то флеш память, то журналирование может не помочь и даже помешать.

pathfinder ★★★★
()
Последнее исправление: pathfinder (всего исправлений: 1)

Как гарантировать, что текстовый файл не побьется при записи, в случае hard reset/poweroff/kernel panic/т.д.?

Это сам по себе странный вопрос. Любая система имеет шанс похерит данные. Обычно требование звучит как нибудь так: «Если система вернула в ответ OK это гарантирует что файл не побился в момент записи.» То есть он может побиться но это не должно стать неожиданностью.

TDrive ★★★★★
()

все зависит от баланса скорости и качества.
наиболее быстрый путь слить файл в ram-кеш и по мере свободности носителя записать его в железку. на современных качественных носителях очень эффективен.
самый качественный путь - записать (fsync или O_DIRECT), а потом прочитать и сравнить с желаемым. но тут скоростью и не пахнет как сам понимаш. и потому многим неинтересно.

pfg ★★★★★
()
Последнее исправление: pfg (всего исправлений: 1)

для этого придумали COW FS и CRC.
или можешь хранить в виде блобов в какой-нибудь базе данных.

Minona ★★☆
()
Ответ на: комментарий от intelfx

ОС думает, что работает с блочным устройством, где блоки 512 байт и есть две неделимые операции «чтение» и «запись». А на самом деле это не так, физически носитель не может делать операции записи блоками меньше 4кБ и вместо двух операций - их три «чтение», «запись нулевых битов» и «стирание». В итоге, чтобы записать виртуальный блок 512 байт, надо считать в память блок 4кБ, затереть его единицами, потом записать нули в нужных местах. Если где-то тут происходит отключение питания, то пострадать может не только записываемый блок 512 байт(как думает файловая система), а некие рандомные другие виртуальные блоки 512 байт, которым не повезло оказаться в одном большом блоке 4кБ.

Вроде может быть как-то так. Но строго говоря, я не специалист. Между жестким диском и флеш-памятью есть отличие в работе, это точно.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

4 кб ?? ты наверно путаешь с размером сектора, которые появились в более позднихх hdd :)
во флеш накопителе оперируют блоками от 128кб и более, в зависимости от модели.
именно наличие больших блоков стирания отличает flash-память от EEPROM.

для флеш накопителя нет операций «стирания» и «заполнение нулевыми битами», есть операция «стирание блока» (который размером в 128кб и более).
нулями он заполнен или единицами это всего лишь вариант преобразования физических параметров в логические данные.

отличий многа, ибо две сильно отличающиеся от друг друга физические системы.

pfg ★★★★★
()
Ответ на: комментарий от pathfinder

Между жестким диском и флеш-памятью есть отличие в работе, это точно.

Ну ты и капитан очевидность.

ОС думает, что работает с блочным устройством, где блоки 512 байт и есть две неделимые операции «чтение» и «запись». А на самом деле это не так, физически носитель не может делать операции записи блоками меньше 4кБ и вместо двух операций - их три «чтение», «запись нулевых битов» и «стирание». В итоге, чтобы записать виртуальный блок 512 байт, надо считать в память блок 4кБ, затереть его единицами, потом записать нули в нужных местах. Если где-то тут происходит отключение питания, то пострадать может не только записываемый блок 512 байт(как думает файловая система), а некие рандомные другие виртуальные блоки 512 байт, которым не повезло оказаться в одном большом блоке 4кБ.

Окей, это всё конечно здорово (хоть и совершенно неверно, т. к. реальная картина куда сложнее и размер блока записи и стирания в NAND-флеше в любом случае разный, поэтому в любом современном SSD уже давно есть слой трансляции адресов, который берёт всю эту работу на себя и любая операция записи данных на SSD в 99.9% случаев не приводит к rmw-циклу), но какое отношение это имеет к журналированию?

intelfx ★★★★★
()
Ответ на: комментарий от izzholtik

EEPROM («истинный» так скажем eeprom, у которых можно стирать каждый отдельный байт) редко где используют объемом больше десятков килобайт, ибо дорого, деление их на блоки бессмысленно, ибо каждый байт полноценно r/w.
у них вообще одна операция «запись байта», стирание идет в комплекте.

все что выше - flash, размеры от единицы (мож и долей) мегабайт.
там две функции записи «записать байт» и «стереть блок».

но никак не «запись нулевых битов» и «стирание» (вот я о чем) посчитаем это за описку.

п.с. операция «чтение байта» есть у всех, ее опускаю.

pfg ★★★★★
()
Последнее исправление: pfg (всего исправлений: 1)
Ответ на: комментарий от pfg

можно стирать каждый отдельный байт

Вообще ни разу таких не встречал, на самом деле)

никак не «запись нулевых битов»

Да это он про то, что типичные «тупые» eeprom'ины при стирании блока забиваются FF'ками, и логически запись поверх стёртого блока выглядит как «прожиг» нулей.

izzholtik ★★★
()
Ответ на: комментарий от intelfx

хоть и совершенно неверно, т. к. реальная картина куда сложнее

Ты тоже капитан очевидность.

но какое отношение это всё имееет к журналированию?

Нужно вести журнал, а это увеличивает число операций записи. Если при отключении питания ФС не может точно знать какие участки носителя при операции записи будут задеты, то это проблема.

Но я не буду спорить. Я когда-то излишне верил в технологию журналирования. А потом в живую несколько раз увидел, как журналирумая ФС (ext3) начинала натурально «глючить» и вытворять странные вещи после грубого отключения питания. Носителем тогда была флеш-память. После этого я в интернете нашел статьи, объясняющие это явление.

Я не занимаюсь носителями информации. Я не специалист. Можешь мне не верить.

pathfinder ★★★★
()
Последнее исправление: pathfinder (всего исправлений: 1)
Ответ на: комментарий от pathfinder

Спасибо. Дискуссия очень интересная.

pacify ★★★★★
() автор топика
Ответ на: комментарий от izzholtik

ну дык конечно. eeprom в среднем в два раза дороже такой же ячейки flash.
в процессе оптимизации структуры, кто-то из инженеров тошибы придумал, что можно объединить элемент записи «1» нескольких ячеек памяти общим электродом и выкинуть из двух транзисторов ячейки один, удешевление в два раза !! так и появился флеш.

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

забивание FF лишь следствием вышеописанного процесса.
в принципе можно было кинуть чутка инверторов в схему управления памятью и забивалось бы «00», но привыкли к FF.

кстати из всех структур флешей используется практически только NAND, ибо их структура на один проводничок меньше, а значит дешевле!! и т.д.

pfg ★★★★★
()
Последнее исправление: pfg (всего исправлений: 2)

Как гарантировать, что текстовый файл не побьется при записи, в случае hard reset/poweroff/kernel panic/т.д.?

что значит не побьётся текстовый файл ? часть незаписанных данных на носитель потеряешь 100% а целостность ФС можно гарантировать COW.

spbob
()
Ответ на: комментарий от pfg

некоторых микроконтроллерах

Там тоже в основном странички, пусть и мелкие, по несколько байт. Кроме самых старых камней.

izzholtik ★★★
()
Ответ на: комментарий от pathfinder

Нужно вести журнал, а это увеличивает число операций записи. Если при отключении питания ФС не может точно знать какие участки носителя при операции записи будут задеты, то это проблема.

А почему это она не знает?

Журналирование работает очень просто. Сначала мы пишем в журнал копию данных, которые будут записаны, вместе с адресом записи и чексуммой. Потом отправляем на диск команду «принудительно сбросить буферы и дождаться окончания всех операций записи» (назовём её командой X). После того, как буферы сброшены, мы записываем те же самые данные уже по месту. При сбое и перезагрузке мы сначала проверяем журнал — если в журнале каша и чексуммы не сходятся, значит, питание пропало в какой-то момент до команды X и содержимое журнала можно отбросить (а пользователю сказать, что записать не успели). Если же в журнале не каша, то питание пропало после команды X — значит, мы повторяем все операции по журналу в порядке их следования, и нам уже не важно, каша ли на диске или нет (потому что все эти данные мы запишем по новой).

Журналирование ломается только в одном случае — если команда X «врёт» и говорит, что всё готово, когда ещё не готово. А если диск при выполнении операции записи по тем или иным причинам способен повредить рядом лежащие сектора, то тут тебя уже ничего не спасёт, ни журналирование, ни без, такой диск можно только выкинуть на помойку.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 2)
Ответ на: комментарий от intelfx

А почему это она не знает?

Насколько я понимаю, обычная ФС, которая работает с блочным устройством, не знает ничего об особенностях носителя. ФС просто работает с набором блоков по 512 байт. Она может считать какой-то блок или что-то записать в него. Но она не знает, что носитель не может записать эти 512 байт, не задев другие блоки.

Мысленно вообразим некий SSD с контроллером и NAND флеш у которой размер блока 512кБ. ФС хочет в некий блок записать данные. Что делает контроллер:

0. [Неведомая магия...] Контроллер определил с каким физическим блоком 512кБ он должен работать.

1. Читает весь блок 512кБ из NAND флеши в некое ОЗУ

2. «Стирает» весь блок. Теперь все биты заполнены единицами.

3. «Записывает» наши 512 байт в нужный кусок блока, а остальное из 512кБ записывает из того, что сохранил в ОЗУ.

Если между стадиями 2 и 3 отключилось питание, то запорчены не 512 байт виртуального блока ФС, а 512кБ физического блока в NAND флеши. Что там лежало - было известно только контроллеру. Наверняка разработчики SSD что-то придумали, чтобы минимизировать риски повреждений данных, но точно уверенным быть нельзя. Остается только верить.

Я это так понимаю, но я не специалист. Может я в чём-то ошибаюсь.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder
1. Читает весь блок 512кБ из NAND флеши в некое ОЗУ

2. «Стирает» весь блок. Теперь все биты заполнены единицами.

3. «Записывает» наши 512 байт в нужный кусок блока, а остальное из 512кБ записывает из того, что сохранил в ОЗУ.

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

spbob
()

ZFS уже безглючно работает на линукс? Может лучше взять нормальную ОС с нативной поддержкой ZFS?

untitl3d
()

Как гарантировать, что текстовый файл не побьется при записи, в случае hard reset/poweroff/kernel panic/т.д.?

Только бэкапом. В общем случае - никак.

LongLiveUbuntu ★★★★★
()

Скорей всего, хватит правильно настроенной EXT4. ZoL очень глючный был 5 лет назад.

Вообще, если нужны именно данные в сохранности, а не минимизация времени у OPS на восстановление системы, то нужно думать про избыточность на уровне блочного устройства. Т.е. какой-нибудь RAID соорудить, на разных дисках. Диски дохнут. Порой, сразу все, если из одной партии.

mv ★★★★★
()

текстовый файл не побьется

Пиши только нетекстовые файлы, тогда текстовые не побьются. Л - логика.

Как гарантировать … в случае hard reset/poweroff/kernel panic/т.д.?

Программно-аппаратным комплексом, не допускающим такие случаи.

anonymous
()
Ответ на: комментарий от anonymous

Отличный выбор!

Офигенный, на самом деле.

Работал в маленьком облаке, там зоопарк рейдов был на нескольких десятках тыщ гипервизоров. Бесперебойников, понятное, на всех не поставишь, и хосты регулярно выключались. Ну и всякие разные кернель паники на таком масштабе постоянно случались. И за каждый DU/DL (data unavailable/data lost) контора кредиты пользователям давала.

Ну так вот, как декомиссовали всё старое железо, с хардварными рейдами, и я штук 10 локапов при скраббинге в софт-рейде перечинил, то DL из-за софта исчез. Да и с локапами ничего не терялось, просто до диска не доходило. Из-за дисков были, там баги в фирмаварях регулярно находятся.

Схема была достаточно простая: RAID-10 или 6/60, device mapper, ext4.

mv ★★★★★
()
Ответ на: комментарий от pathfinder

ФС хочет в некий блок записать данные. Что делает контроллер: <…>

Абсолютно неверно, читай выше что я написал и гугли про FTL.

Я это так понимаю, но я не специалист. Может я в чём-то ошибаюсь.

Ну хотя бы это понимание присутствует, уже неплохо.

Ещё раз повторяю: если диск [предоставляющий классическую абстракцию LBA, про host-managed зонированные блочные устройства, сырой флеш и прочую экзотику речи не идёт] при выполнении операции записи по тем или иным причинам способен повредить рядом лежащие сектора, то тут тебя уже ничего не спасёт, ни журналирование, ни без, такой диск можно только выкинуть на помойку.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)

Как гарантировать, что текстовый файл не побьется при записи, в случае hard reset/poweroff/kernel panic/т.д.?

Никак, потому что, например, железо может накрыться сразу после успешной записи. С точки же зрения кода, который файл записывает, нужно:

  • флашнуть буфферы, если таковые в коде используются (например, fflush() в случае stdio, std::flush в плюсах, ничего если просто вызывал write())
  • вызвать fsync() проверив возвращаемое значние
  • закрыть дескриптор проверив возвращаемое close() значание

После этого ответственность переходит ядру и файловой системе.

В питоне я использую такой паттерн:

with open('foo', 'w') as filedesc:
    # write to filedesc
    filedesc.flush()
    os.fsync(filedesc.fileno())

Какая файловая система устойчива к таким случаям. Встречал, что с ZFS под Linux были проблемы.

Должна быть любая, это её наипервейшая обязанность. Но в Linux большинство ФС кривые, особенно XFS, для которой официально документированное поведение - херить данные. А вот например ZFS на FreeBSD мы stress-тестили на эту тему, проблем не обнаружено. YMMV.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от mv

Бесперебойников, понятное, на всех не поставишь

ну если пытаться ставить их отдельно к каждому серверу, то конечно. но в контексте нормальных дц твоё утверждение мягко говоря не корректно

anonymous
()
Ответ на: комментарий от anonymous

ну если пытаться ставить их отдельно к каждому серверу, то конечно. но в контексте нормальных дц твоё утверждение мягко говоря не корректно

Продолжай. Или ты про dual feed? Оно тоже кончается.

mv ★★★★★
()
Ответ на: комментарий от anonymous

ДЦ много по шарику разбросано. Но обычно выпиливается питальный шкаф на несколько стоек, а не весь ДЦ ложится. Хотя и такое тоже случается.

mv ★★★★★
()
Ответ на: комментарий от LongLiveUbuntu

В несколько мест записывать

А если при попытке создания первой копии произойдёт power off?

pacify ★★★★★
() автор топика

ZFS синхронна на запись по умолчанию.

iZEN ★★★★★
()

SQLite не обеспечивает целостности данных и ничего не гарантирует. Берите InterBase.

iZEN ★★★★★
()

Встречал, что с ZFS под Linux были проблемы.

ZFS слабо совместима с vfs Linux. Берите Illumos или FreeBSD.

iZEN ★★★★★
()
Ответ на: комментарий от intelfx

Журналирование ломается только в одном случае — если команда X «врёт» и говорит, что всё готово, когда ещё не готово. А если диск при выполнении операции записи по тем или иным причинам способен повредить рядом лежащие сектора, то тут тебя уже ничего не спасёт, ни журналирование, ни без, такой диск можно только выкинуть на помойку

И это 95% всех SSD накопителей. После якобы успешного fsync повреждают они не просто случайные «соседние» блоки. а те, которые писались скопом в момент внезапного отключения. То есть, они могут быть вообще не соседние в плане LBA. В принципе, с предложенным методом утилизации данных накопителей я согласен. Сам держу SSD в основном под read-only данные, вроде системы и программ. А БД на таком носителе держать — это задача, посильная лишь секс-гигантам, потому что после сбоя восстановиться можно только из бэкапа или зеркала.

byko3y ★★★★
()
Ответ на: комментарий от pacify

Связка InterBase + FreeBSD работает только для x86 ?

Самому интересно.

iZEN ★★★★★
()
Ответ на: комментарий от spbob

мне кажется там всё проще - секторы дописывают в другой блок и меняют ссылку в таблице. Как только в блоке нет секторов на которые ссылается таблица блок очищается и он готов для записи

Всё сложнее, и потому SSD, как правило, не подлежат восстановлению. «Простые» линуксовые ФС для флеша хранили и изменяли статусы блоков в оперативной памяти, никак не записывая этот «индекс» на сам флеш, а вместо этого восстанавливая «индекс» полным сканированием ФС. Контроллер SSD же усложняется тем, что его блок намного больше блока ФС, потому контроллер группирует записи, максимально сокращает число записей в постоянное хранилище, и, грубо говоря, дописывает все изменения «в конец» диска, как во write-head log, и эти изменения представляют собой кашу из метаданных вместе с данным: «поменяли 512 байт блока с LBA таким-то, поменяли 1024 байт блока с LBA эдаким» — это если очень-очень упростить содержимое, опуская служебные структуры, которые нужны, например, для того, чтобы прыгнуть на начало файла или на второй мегабайт без необходимости сканировать весь лог.

По поводу «стирания» — я боюсь, что это самый сложный алгоритм в контроллере. Поскольку когда у вас имеется вот такая переплетенная лапша из записей по разным адресам, то нахождение там «лишних» записей становится весьма непростой задачей, для решения которой на переполненном диске понадобится перетряхивание блоков, и, вполне возможно, потому ОС доступно меньше памяти, чем на самом деле есть в SSD, а не просто «чтобы были запасные блоки при отказах».

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Ты прав в том (сообщение ниже), что современные SSD по сути представляют собой log-structured хранилище. И как ни странно, crash resistance в таких структурах данных — это решённая задача.

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

Ты прав в том (сообщение ниже), что современные SSD по сути представляют собой log-structured хранилище. И как ни странно, crash resistance в таких структурах данных — это решённая задача

И как же она решена? Да, блоки, которые вообще никто не меняет, не посыпятся, но если диск интенсивно пишется в самые разные места, то только Аллах знает, что удастся оттуда прочитать после внезапного выключения. А это в том числе касается метаданных ФС, таких как каталоги и имена файлов. Я догадываюсь, что ты возражаешь только на «я изменил 4 кБ, а контроллер испортил соседние 512 кБ» — с чем я точно так же спорил. И я полностью согласен с тем, что уже давно SSD не выдают целиком испорченную ФС после падения. А иногда выдают. А иногда сыпятся просто так во время работы. Потому что хер его знает, как работает проприетарная прошивка и сколько в ней багов. Меньше, чем на заре становления SSD, но все равно не нулевое число.

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.