MAATRIX / Блог / Файл открывался десять лет, а на одиннадцатый стал мусором

Файл открывался десять лет, а на одиннадцатый стал мусором

MAATRIX

Файл лежал на диске одиннадцать лет, ни разу не подводил, а потом в один момент отказался открываться — программа выдавала ошибку формата, будто файл никогда и не был рабочим. Никто его не трогал, не редактировал, не переносил — он просто лежал в архиве. Это не мистика и не редкий баг конкретного приложения, а достаточно известное в индустрии хранения данных явление: тихая порча данных, или bit rot. Разберём, что физически происходит с носителем за годы простоя, почему именно архивные файлы страдают сильнее всего и что с этим делать на практике, не дожидаясь момента, когда важный файл откроется мусором.

История: файл, который был здоров десять лет и умер на одиннадцатый

Ситуация встречается чаще, чем кажется, и у неё всегда один и тот же сценарий. Есть файл — архив базы данных, сканы документов, видеозапись, дистрибутив старого проекта — который записали на диск много лет назад и с тех пор не открывали. Диск при этом жил обычной жизнью: работал в сервере или во внешнем накопителе, иногда включался, иногда простаивал месяцами. Файловая система не жаловалась, fsck не находил ошибок, SMART-статус диска показывал "здоров". А потом файл понадобился — и выясняется, что он битый: архив не распаковывается, видео зависает на середине с артефактами, база данных при восстановлении падает с ошибкой контрольной суммы страницы.

Разница между этим сценарием и обычным отказом диска принципиальна. При отказе диска вы получаете явную ошибку: диск не виден, сектор не читается, dmesg сыплет предупреждениями ввода-вывода. Здесь же диск исправно возвращает данные по каждому запросу чтения, аппаратных ошибок не фиксируется — просто содержимое файла уже не то, что было записано одиннадцать лет назад. Несколько бит незаметно "поплыли", а файловая система об этом ничего не знает, потому что и не умеет это отслеживать.

Дальше — почему так происходит на физическом уровне и почему проблема касается в первую очередь архивных, редко читаемых данных.

Что физически происходит с носителем за годы

Любой способ хранения цифровых данных — это способ зафиксировать состояние физического материала: намагниченность участка пластины, заряд в ячейке памяти. Эта фиксация не абсолютна и не вечна — физическое состояние носителя постепенно смещается в сторону "естественного", и это смещение со временем превращается в перевёрнутые биты.

На жёстких дисках (HDD) данные хранятся как направление намагниченности крошечных доменов на вращающейся пластине. Магнитное поле домена со временем может ослабевать — из-за тепловых колебаний, влияния соседних дорожек при их перезаписи (эффект, который в индустрии называют adjacent track interference), и старения самого магнитного слоя. Пока домен читается уверенно, головка и контроллер интерпретируют его правильно. Когда сигнал ослабевает настолько, что становится неоднозначным, бит может прочитаться неверно — и если это не превысило порог коррекции ошибок на уровне диска, наружу, на уровень операционной системы, ошибка не всплывёт вообще.

На SSD и других носителях на базе флеш-памяти (NAND) механизм другой, но результат похожий. Данные хранятся как заряд в изолированной ячейке транзистора, а изолирующий слой со временем понемногу "протекает" — заряд утекает, особенно если накопитель долго стоит без питания. Это задокументированная характеристика флеш-памяти, и производители закладывают её в спецификации хранения данных без питания (обычно это месяцы, а не годы, если накопитель уже изношен). Плюс естественный физический шум: космические лучи и фоновая радиация статистически способны переворачивать отдельные биты в памяти — задокументированное явление, актуальное и для оперативной памяти без ECC.

Важный нюанс: диск чаще всего *пытается* защититься от таких ошибок — на уровне контроллера почти всегда есть коды коррекции (ECC), которые исправляют небольшое количество перевёрнутых бит незаметно для вас. Проблема начинается там, где повреждение превышает возможности встроенной коррекции, но остаётся недостаточным, чтобы диск сообщил явную ошибку чтения — тогда он молча отдаёт искажённые данные как корректные.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Почему файловая система не бьёт тревогу

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

Логика по-своему разумная: за целостность данных на уровне бит по умолчанию отвечает диск и его встроенная коррекция ошибок, а не файловая система сверху. Пока диск не сообщает об ошибке чтения, файловая система считает операцию успешной и передаёт байты приложению как есть. Если контроллер диска не заметил повреждение (оно осталось за порогом ECC, но всё равно исказило данные), то ни ext4, ни NTFS этого тоже не заметят. Проверка целостности на уровне файловой системы — не базовая функция, а осознанный выбор архитектуры, который есть далеко не везде.

Есть файловые системы, спроектированные иначе — ZFS и Btrfs хранят контрольную сумму для каждого блока данных и проверяют её при каждом чтении, а не полагаются только на диск. Если данные не совпадают с контрольной суммой, такая файловая система как минимум сообщит об ошибке, а при наличии избыточности (зеркало, RAID-Z) — восстановит блок автоматически. Подробнее о механизме контрольных сумм и о том, как это работает на практике, — в отдельном разборе про тихую порчу файлов и контроль целостности. Но большинство архивов на практике лежит именно на ext4, NTFS или в облачном хранилище поверх них — и там этой защиты по умолчанию нет.

Почему архивные файлы страдают сильнее всего

Тут и кроется главная опасность именно для редко используемых данных. Bit rot — процесс постепенный и статистический: чем дольше файл лежит без чтения и перезаписи, тем больше накопленное время для деградации намагниченности или утечки заряда, и тем выше шанс, что где-то в файле уже "поплыл" бит.

Файлы, которые читаются регулярно, косвенно защищены самим фактом обращения к ним: программа пожалуется на ошибку формата, пользователь увидит артефакт в видео, чек-сумма при копировании не сойдётся. А если файл открывают раз в год на аудите или вообще никогда, кроме момента "внезапно понадобилось" — деградация копится молча, без единого сигнала, который бы кто-то заметил.

Хуже того: рутинные процессы, которые как будто должны защищать архив, зачастую этой проблемы не решают, а иногда маскируют её ещё сильнее.

  • Резервное копирование копирует байты, а не проверяет их корректность. Стандартный rsync без флага --checksum сравнивает файлы по размеру и времени модификации — если файл на архивном диске не менялся, rsync решит, что копировать нечего, и оставит в бэкапе старую, уже подпорченную копию. Хуже, если это первичное копирование "битого" файла — порча аккуратно реплицируется в бэкап, и точка отсчёта здорового состояния теряется.
  • Ротация бэкапов со временем вытесняет здоровые версии. Если политика хранения держит только 4 последних квартальных снапшота, а порча случилась 5 циклов назад и осталась незамеченной — последняя здоровая копия уже удалена по расписанию.
  • RAID и облачная избыточность не спасают от этого сценария, потому что защищают от отказа целого диска, а не от посекторного искажения данных, которое штатно реплицируется на все копии массива — подробнее в материале про миф "RAID — это резервная копия".

Итог: наличие бэкапа само по себе не гарантирует, что в нём лежит здоровая версия файла. Гарантирует это только проверка.

"У нас есть бэкап" — не то же самое, что "данные целы"

Это самая опасная иллюзия в разговоре про архивы. Наличие резервной копии закрывает один конкретный риск — потерю данных при физическом отказе носителя целиком (сгорел контроллер, умер диск, украли сервер). Оно не закрывает риск постепенной порчи, потому что процесс резервного копирования по умолчанию не спрашивает "а не испортился ли этот файл со времени последней проверки" — он спрашивает "изменился ли этот файл со времени последнего бэкапа", и это два разных вопроса.

Показательный пример: если бэкап делается инкрементально и ориентируется на дату изменения файла, а исходный файл на архивном диске давно не менялся (что для архива нормально), новый бэкап-цикл его просто пропустит как "без изменений". Испорченный файл может годами лежать нетронутым и в оригинале, и в бэкапе — все копии синхронно нездоровы, просто никто их не читал и не сверял.

Отсюда практический вывод для любого архива дольше пары лет: бэкап отвечает на вопрос "куда восстанавливаться, если диск умрёт физически", а контроль целостности — на вопрос "восстановится ли на самом деле что-то рабочее". Это две разные задачи, и одна не заменяет другую.

Как проверять целостность архива на практике

Хорошая новость — задача решается инструментами, которые уже есть в любом Linux-дистрибутиве, без специального железа. Идея простая: зафиксировать контрольную сумму файла в момент, когда он точно здоров, и периодически её пересчитывать, сравнивая с зафиксированной.

Для отдельных файлов и небольших архивов достаточно обычных хеш-сумм:

# зафиксировать контрольные суммы каталога архива
find /mnt/archive -type f -exec sha256sum {} \; > archive.sha256

# при следующей проверке — сверить с зафиксированным состоянием
sha256sum -c archive.sha256 --quiet

Если строка не проходит проверку — это либо законное изменение файла (тогда пересчитайте и зафиксируйте заново), либо то самое незаметное искажение, которое стоит расследовать: попробовать восстановить файл из более старой копии, пока такая копия ещё существует.

Для больших коллекций файлов, где вручную такое не проконтролировать, разумно завести периодическую задачу в cron — раз в месяц или квартал, в зависимости от того, насколько критичен архив:

# /etc/cron.monthly/verify-archive
#!/bin/bash
LOGFILE=/var/log/archive-verify.log
cd /mnt/archive || exit 1
if ! sha256sum -c archive.sha256 --quiet >> "$LOGFILE" 2>&1; then
    echo "Archive integrity check FAILED, see $LOGFILE" | mail -s "Archive alert" admin@example.com
fi

Отдельно стоит проверять то, что бэкап действительно сравнивает содержимое, а не только метаданные. Для rsync это флаг --checksum (медленнее, зато честно читает содержимое обеих сторон, а не полагается на время модификации):

rsync -avc --dry-run /mnt/archive/ /mnt/backup/archive/

Для файловых систем с поддержкой контрольных сумм на уровне блоков — ZFS и Btrfs — есть встроенный механизм фоновой проверки, который делает практически то же самое, но автоматически и на уровне блоков, а не файлов целиком:

# ZFS — плановая проверка пула
zpool scrub tank
zpool status tank   # посмотреть результат и статистику ошибок

# Btrfs — аналогичная проверка
btrfs scrubbing start /mnt/archive
btrfs scrubbing status /mnt/archive

Если ресурс позволяет перенести архив на такую файловую систему — это снимает необходимость вручную считать контрольные суммы, проверка и восстановление происходят автоматически. Если нет — ручная схема с sha256sum и cron-задачей всё равно закрывает основной риск, просто требует чуть больше дисциплины. Разбор вариантов хранения архивов "на холодную" — на медленных дисках, в облаке или офлайн — есть в материале про холодное хранение архивов.

Отдельно полезно держать избыточность самого содержимого, а не только его копий — утилиты вроде par2 создают файлы восстановления, которые позволяют исправить небольшое число повреждённых байт без обращения к резервной копии:

# создать файлы восстановления с запасом ~5% от объёма
par2create -r5 archive.par2 archive.tar.gz

# позже — проверить и, если нужно, восстановить
par2verify archive.par2
par2repair archive.par2

Ни один из этих способов не требует дорогого оборудования — это дисциплина и немного места под контрольные суммы и файлы восстановления, для архива в терабайтах обычно копеечная доля объёма.

Практические выводы

Несколько правил, которые стоит применить к любому архиву старше года-двух:

  • Не путайте наличие бэкапа с гарантией целостности. Бэкап защищает от потери диска целиком, а не от постепенной порчи содержимого — это разные механизмы и разные проверки.
  • Заводите контрольные суммы в момент архивации, а не постфактум, когда уже неясно, был ли файл здоров изначально.
  • Проверяйте архив периодически, а не только когда он реально понадобился — иначе узнаёте о проблеме в худший момент, когда времени на восстановление из старой копии может не остаться.
  • Для действительно важных данных рассматривайте файловые системы с контролем целостности блоков (ZFS, Btrfs) — они переносят эту заботу с человека на систему.
  • Держите несколько поколений бэкапов, а не только последний — если порча реплицировалась в бэкап незамеченной, шанс на восстановление даёт только старая, ещё здоровая версия.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Как понять, что дело именно в тихой порче данных, а не в отказе диска?

Если SMART-статус в порядке, ошибок чтения в dmesg и логах контроллера нет, а конкретный файл при этом повреждён — это признак постепенного искажения содержимого, а не аппаратного отказа. Для уверенности стоит проверить диск на битые сектора (badblocks в режиме только чтения) — если их нет, дело в содержимом файла, а не в носителе.

Обязательно ли переходить на ZFS или Btrfs, чтобы защититься от bit rot?

Нет, это самый надёжный вариант, но не единственный. Ручная схема с пересчётом контрольных сумм (sha256sum + cron) и файлами восстановления (par2) закрывает тот же риск на ext4, NTFS и в облачном хранилище — просто требует, чтобы её реально настроили и не забыли выполнять по расписанию.

Правда ли, что SSD в этом смысле надёжнее HDD?

Не обязательно — механизм другой, риск сопоставим. У HDD деградирует намагниченность, у SSD без питания утекает заряд в ячейках NAND, оба процесса статистические и растянуты во времени. Точных цифр по срокам разумно не приводить — они сильно зависят от модели, износа и условий хранения, но ограниченный срок хранения данных без питания сами производители закладывают в спецификации.

Может ли облачное хранилище (S3-совместимое, Google Drive и подобные) само защитить от этой проблемы?

У серьёзных объектных хранилищ обычно есть внутренние механизмы контроля целостности на стороне провайдера, но это не повод полагаться на них вслепую — у вас нет способа проверить, что это действительно работает для вашего конкретного файла. Собственная контрольная сумма, зафиксированная до загрузки и сверяемая при скачивании, — дешёвая страховка независимо от того, кому вы доверяете хранение.

С чего начать, если у меня уже есть большой архив без единой контрольной суммы?

Начните сейчас: посчитайте sha256sum по всему архиву и зафиксируйте результат — это не докажет, что файлы здоровы прямо сейчас, но создаст точку отсчёта, от которой будет видно любое дальнейшее изменение. Дальше по возможности сверьте текущее состояние со старейшей доступной резервной копией — если расхождение есть, а старая копия ещё жива, это последний шанс понять, какая версия здоровая, до того как её заменят по ротации.

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →