Комментарии к «невосстановимому бэкапу»

KDV, 05.11.2003
Комментарии к http://www.ibase.ru/norestore/

См. начиная с " ...логические ограничения, нарушение которых приводит к..."

а) пункты 1 и 3, т. е. наличие null в добавленных столбцах not null. В отличие от check (дальше) указание not null находится прямо у стольбца в rdb$fields и rdb$relation_fields (RDB$NULL_FLAG).

Поэтому либо нужно проверять при чтении записей наличие null в not null столбце и выдавать сообщение при backup, либо игнорировать not null при restore (либо не игнорировать, а выставлять not null после заливки данных).

Здесь надо чуть отвлечься, и отметить что backup-ов может быть 2:
  • Первый игнорирует ошибки как сейчас, но допускает "щадящий" restore, т. е. независимо от типа "повреждений" БД позволяет ее восстановить.
  • И второй, который ни в коем случае не делает бэкап при наличии "ошибок".
Причем скорее всего, что обе реализации должны быть. Как для strong data checking так и для restore in any case (прошу прощения, что по-английски).

Продолжаем.

б) неупомянутый в перечне случай, когда применялся alter типа (размера) столбца при наличии неконвертируемых данных (alter строки в число).

Не упомянуто правильно, потому что ошибка конвертации будет показана именно на этапе backup. Т. е. сделать бэкап с неконвертируемыми данными не получится (как впрочем, не получится сделать некорректное преобразование через alter table. А если разработчик сам такое сделал путем прямой модификации системных таблиц, то он и виноват).

в) check constraints, наложенные на некорректные данные, пункты 2 и 4. Собственно, если возможность создать такой check constraint существует, то при restore надо все check constraints (rdb$check_constraints, и check в rdb$triggers) создавать в метаданных после восстановления данных. И только так. Это приведет к изменению формата backup, т.к. в текущем варианте последовательность сохранения данных совершенно однозначная, и данные восстанавливаются после восстановления всех метаданных. Необходимо отметить, что сейчас у gbak есть ключ -no_validity, который не восстанавливает check constraints.

При таком изменении в gbak мы получим ситуацию, когда данные, нарушающие check constraints, могут быть долго не обнаружены в БД. Поскольку обратная ситуация, т. е. появление данных, нарушающих check constraints, после создания check constraints возможна разве что при повреждении БД, то можно считать отсутствие проверок соответствия данных check constraints при backup/restore нормальным поведением сервера.

г) Primary, Unique и Foreign key, индексы вообще, пункты 5, 6 и 7. Никаких сложностей. Эти constraints контролируются индексами, которые создаются после восстановления данных из backup. Если индекс PK, FK, UNIQUE не смог "восстановиться", то он остается в состоянии rdb$index_inactive = 3. Основная проблема в том, что ошибка при создании индекса (нарушение уникальности, нехватка места в temp и т. п.) приводит к остановке процесса восстановления всех индексов. Т. е. при ошибке на первом индексе ни один больше не восстановится (и все индексы придется восстанавливать руками, меняя указанное значение с 3 или 1 на 0 прямо в rdb$indices). Поэтому предложение состоит в том, чтобы сделать сообщение об ошибке восстановления конкретного индекса не ERROR, а WARNING.

При этом часть систем может считать такую БД восстановленной успешно, а часть – нет, и потребует ручного вмешательства администратора. В любом случае, количество ручной работы по восстановлению индексов при warning будет минимизировано.

д) пункт 8 – относится к restore только метаданных. Это просто должно быть исправлено в gbak, без учета всех остальных пунктов.

е) вложенные вызовы процедур из процедур и триггеров, с несоответствием параметров. Здесь удивляет скурпулезность ядра, которое не перекомпилирует текст процедур и триггеров при restore, но тем не менее проверяет соответствие blr и rdb$procedure_parameters. Опять же, как и для пункта "в", если ядро допускает такое "на ходу", то и restore должен производиться с игнорированием подобных "казусов".

Некоторые разработчики предлагают автоматизировать процесс backup добавляя туда контрольный restore. На больших объемах это может стать неоправданным (по времени или расположению файлов backup и БД). Как раз для пунктов "д" и "е" имеет смысл выполнять контрольный restore метаданных, причем в начале процесса backup.

Т. е. пока, без автоматизации примерная последовательность backup с тестовым restore представляется такой:
  1. бэкап метаданных >gbak -b db.gdb db.gbk -m
  2. контрольный рестор метаданных >gbak -c db.gbk test.gdb
  3. если пункт 2 прошел успешно, то в базе нет явных проблем с метаданными ("д", "е" и др. варианты). test.gdb можно удалить.
  4. бэкап (без сборки мусора, макс. скорость) >gbak -b -g db.gdb db.gbk (ключи -v -y – по вкусу, желательно)
  5. контрольный рестор >gbak -c db.gbk test.gdb (ключи -v -y по вкусу, желательно)
  6. сравнение скриптов оригинальной БД и восстановленой в п.5 БД (через dbcomparer)

Если пункт 5 (и 6) прошел, то имеющися бэкап на 100 % восстановим (также можно считать, что дефектного "железа" нет, т. е. оно не внесло искажений в backup/restore). При желании можно удалить db.gdb и переименовать temp.gdb. Сохранять в архив можно как db.gbk так и temp.gdb.

Учитывая будущие изменения в gbak данную схему можно изменить:

Жесткий контроль: backup с ключом, контролирующим not null и конвертацию данных. Если есть ошибки, то бэкап не пройдет. Т. е. если этап 4 выполняется в таком режиме, то в случае ошибки мы исключаем пункт 5 (не тратим на него время) и начинаем "чинить" имеющуюся базу данных до успешного выполнения пункта 4.

Отсутствие контроля: restore с ключом, игнорирующим not null и конвертацию данных (и все остальные ошибки по пунктам "д", "е". Итоговая БД в смысле логических ошибок будет идентична имеющейся БД. При соблюдении в gbak всех случаев контроля и не-контроля данных такой restore можно считать штатным в "аварийных" случаях, т. е. когда БД повреждена.

Еще раз хотелось бы отметить, что существуют физические и логические повреждения данных, которые могут нарушить целостность данных. Сейчас это приводит к "невосстановимости backup". Если ликвидировать "логические повреждения" путем перечисленного выше контроля и не-контроля, то останутся только проблемы с физическим повреждением данных, которые выходят за рамки обеспечения backup/restore в нормальных условиях.

Подпишитесь на новости Firebird в России

Подписаться