Эта страница переведена машинным переводом. Читайте английский оригинал. English

Библиотека IBSurgeon

«Cannot commit index» или как выкачать данные из частично восстановленной (несогласованной) базы данных

Alexey Kovyazin, последнее обновление 30 марта 2014 г.

После исправления повреждений часто возникает ошибка “Cannot commit index” на этапе восстановления. В Firebird 2.0 и более поздних версиях это выводится как предупреждение, и база данных не будет переведена в онлайн-режим; в Firebird 1.0-1.5 и InterBase это происходит как очень неприятная ошибка, которая останавливает процесс восстановления (впечатляет увидеть эту ошибку в конце восстановления базы данных размером 200 ГБ).

Причина ошибки “Cannot commit index..” очевидна: повреждение затрагивает ссылочную целостность базы данных, и записи исчезают магическим (с точки зрения сервера) образом.

Например, у вас есть таблица “Customers” и связанная таблица “Orders”, на которую ссылается внешний ключ. Без повреждения невозможно нарушить внешний ключ и удалить запись из Customers без предварительного удаления всех заказов, которые ссылаются на конкретного клиента. Повреждение затрагивает файл базы данных на низком уровне и удаляет записи напрямую. Каким приятным сюрпризом для сервера является обнаружение неразрешенных ссылок на главные записи из записей внешних ключей.

Здесь мне нужно добавить совет о процессе восстановления: движок восстанавливает все таблицы с неактивированными индексами (это делает заполнение таблиц записями намного быстрее), а затем начинает активировать (т.е. строить) индексы один за другим. Это означает, что все данные уже находятся в базе данных, когда процесс восстановления начинает этап создания индексов, и вы видите ошибку “Cannot commit index..”.

Итак, первое желание при появлении ошибки “Cannot commit index” - удалить соответствующий внешний ключ, чтобы позволить восстановлению завершиться. Вопрос в том, что мы будем делать с несогласованной, но успешно восстановленной базой данных: удаленный внешний ключ может быть важной частью бизнес-логики.

Здесь есть 2 подхода: воссоздать недостающие данные или удалить несогласованные данные. Давайте посмотрим, что это означает на примере Customers-Orders выше.

Воссоздание недостающих данных

Итак, вы решили, что вам нужно воссоздать недостающих клиентов для несогласованных заказов. Для этого вам нужно определить потерянные ID. Обычно я использую такой SQL-запрос (думаю, его будет легко адаптировать под вашу ситуацию):

SELECT O.Customer_ID FROM ORDERS O WHERE NOT EXISTS ( SELECT C.Customer_ID FROM CUSTOMERS C WHERE O.Customer_ID=C.Customer_ID)

После этого вы можете вручную вставить записи со списком недостающих первичных ключей и снова запустить резервное копирование/восстановление.

Перекачка согласованных данных

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

  1. Скачайте бесплатный инструмент IBDataPump http://www.clevercomponents.com/demo/datapump/IBPump.zip

  2. Создайте только метаданные базы данных из резервной копии восстановленной базы данных (после IBFirstAID) с помощью команды

gbak -c -m -user SYSDBA -pass masterkey Disk:\Path\backup.fbk Disk:\Path\fresh.fdb

  1. Запустите IBDataPump и установите частично восстановленную базу данных как источник, а новую пустую базу данных как цель

  2. Перейдите на следующие вкладки, нажмите соответствующие кнопки и на 3-й вкладке нажмите “Pump”. Дождитесь завершения (это может быть длительный процесс; чтобы получить представление, вы можете проверить динамику роста размера целевой базы данных).

  3. В результате у вас будет база данных fresh.fdb с согласованными связями внешних ключей - это полностью нормально.

Если в базе данных есть циклы внешних ключей, IBDataPump предупредит вас и предоставит список таких ограничений - одно или несколько из них должны быть удалены, прежде чем перекачка станет возможной.

Конечно, были случаи, когда перекачка требовала особого подхода, и если вы столкнетесь с такой ситуацией, пожалуйста, свяжитесь с нашей службой поддержки.