Восстановление данных из повреждённой базы Firebird
База Firebird перестала открываться, запрос падает с internal Firebird consistency check, или gbak не может сделать бэкап. Здесь описан порядок действий, который спасает больше всего данных: от самых безопасных шагов к самым радикальным. На страницах ошибок — что значат частые сообщения.
Сначала: сделайте копию и работайте только с ней
Остановите сервер 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 выбрасывает записи, которые не может прочитать, поэтому сравните результат с оригиналом, прежде чем на него полагаться.
Если 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 делает с повреждениями
- Повреждённые записи пропускаются и попадают в список, остальная таблица выгружается.
- Повреждённые или обнулённые страницы. Строки на них потеряны, остальная база — нет. Страницы данных, до которых уже не ведут pointer-страницы таблицы, находятся сканированием всего файла.
- Страницы не на своём месте читаются там, где лежат: Firebird 3 и новее хранит номер страницы на самой странице.
- Повреждённая таблица транзакций (
cannot find tip page). Строки всё равно выгружаются. Где состояние транзакции потеряно, берётся самая новая версия строки, с предупреждением. - Повреждённый заголовок. Размер страницы и версия определяются по остальному файлу.
- Потерянные описания таблиц. Таблицы и колонки выгружаются под условными именами (
TABLE_131,FIELD_2). Если потеряны сами форматы записей, передайте fbrescue операторы CREATE TABLE вашей базы (--ddl schema.sql): скрипт создания, выводisql -xили выгрузку fbrescue, сделанную раньше.
Сколько данных возвращается при каждом виде повреждения, измерено на сотнях повреждённых копий тестовой базы в Firebird 2.5, 3.0, 4.0 и 5.0 — см. таблицу восстановления.
fbrescue достаёт данные, но не чинит сам файл. Индексы, триггеры, процедуры и пользователи не выгружаются — создайте их заново в новой базе. Чем fbrescue отличается от gfix/gbak и IBSurgeon FirstAID — в сравнении, короткие ответы — в FAQ.
База цела, но открыть её нечем?
Та же утилита выгружает и неповреждённые базы: открыть .fdb без Firebird, выгрузить в CSV и Excel, перенести данные в PostgreSQL.
Частые ошибки
internal Firebird consistency check (decompression overran buffer (179))— повреждены байты записиinternal Firebird consistency check (wrong record length (183))— запись не совпадает с форматом таблицыinternal Firebird consistency check (cannot find tip page (165))— повреждена таблица состояний транзакцийdatabase file appears corrupt/page is of wrong type— на странице не то, что должно бытьI/O error during "read" operation— файл короче базы или сбоит дискgbak: ERROR…Exiting before completion due to errors— бэкап повреждённой базы обрывается