fbrescue

internal Firebird consistency check (decompression overran buffer (179))

Полностью сообщение обычно выглядит так: internal Firebird consistency check (decompression overran buffer (179), file: sqz.cpp line: ...). Оно появляется в запросе, в gbak или в gfix -v.

Что это значит

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

Сначала: сделайте копию и работайте только с ней

Остановите сервер Firebird или хотя бы убедитесь, что к базе никто не подключён. Скопируйте файл вместе с .delta-файлом рядом с ним, если он есть (блокировка nbackup), и вторичными файлами многофайловой базы. Копия, снятая во время записи, несогласованна, а любая попытка починки меняет файл, с которым работает. Если сбоит сам диск, первым делом перенесите файл на другой диск.

Затем: попробуйте штатные средства Firebird

Они есть в каждой установке Firebird и часто возвращают базу целиком — с индексами, триггерами и пользователями. На копии:

gfix -v -full -n copy.fdb            # проверка, только отчёт
gfix -mend -full -ignore copy.fdb    # gbak пропустит битые записи
gbak -b -v -ig -g copy.fdb copy.fbk  # бэкап без контр. сумм и GC
gbak -c -v copy.fbk restored.fdb     # восстановление в новую базу

Добавьте -user SYSDBA -password ..., если этого требует сервер. Если gbak -b завершился, результат — восстановленная база: сверьте число строк в важных таблицах. gfix -mend выбрасывает записи, которые не может прочитать, поэтому сравните результат с оригиналом, прежде чем на него полагаться.

gfix -mend — штатный ответ движка именно на эту ошибку: он помечает повреждённую запись, и следующий бэкап её пропускает.

Если gbak всё равно не проходит: выгрузите данные через fbrescue

fbrescue читает файл базы напрямую, без движка Firebird, и выгружает все строки, которые удаётся прочитать. Он не останавливается на первой повреждённой записи или странице и никогда не пишет в файл. Скачайте бинарник для своей системы на странице Releases: Windows, Linux, macOS, устанавливать ничего не нужно.

fbrescue scan copy.fdb                               # что повреждено, по таблицам
fbrescue export copy.fdb --out rescued --format sql  # schema.sql + INSERT'ы по таблицам

Есть также --format csv и --format jsonl. Строки, которые не удалось прочитать, перечислены в rescued/_errors.jsonl со страницей и причиной; если что-то не выгрузилось, код выхода — 2. Загрузить результат в новую базу:

isql -ch UTF8 -i rescued/schema.sql new.fdb
isql -ch UTF8 -i rescued/CUSTOMERS.sql new.fdb  # и так для каждой таблицы

Нужна помощь — откройте issue и приложите вывод fbrescue report copy.fdb. Отчёт описывает повреждения без ваших данных, имена таблиц и колонок в нём заменены номерами.

При этой ошибке fbrescue читает все записи таблицы и выгружает остальные. Записи, которые не распаковываются, попадают в _errors.jsonl со страницей и строкой. Запись, которая продолжается на другой странице (такое бывает с записями больше страницы), теряется, только если повреждён один из её кусков.

См. также