fbrescue

database file appears corrupt / page ... is of wrong type

Обычно они идут вместе: database file appears corrupt (...), затем wrong page type и page 1234 is of wrong type (expected 5, found 0).

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

База Firebird — это файл из страниц одного размера. В первом байте каждой страницы записан её тип: данные, индекс, pointer, blob, таблица транзакций и так далее. Движок перешёл по ссылке на страницу 1234, ожидая один тип, а нашёл другой. found 0 значит, что страница обнулена. Так бывает после падения сервера, сбоя диска, починки файловой системы или неудачного копирования. Другое число обычно значит, что на странице лежит содержимое другой страницы.

Что потеряно, зависит от того, какая это страница:

Тип страницы (ожидался) Что потеряно
5, данные строки на этой странице
4, pointer для движка — перечисленные там страницы данных таблицы; сами страницы целы
7, индекс ничего: индексы строятся заново из данных
8, blob значения BLOB на этой странице
3, таблица транзакций см. cannot find tip page

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

Остановите сервер 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 scan покажет все страницы, которые не такие, какими должны быть, а по каждой таблице — сколько страниц данных и записей до неё доступно. При выгрузке:

См. также