Цю сторінку перекладено машинним перекладом. Читайте англійський оригінал. English

Бібліотека IBSurgeon

"Неможливо зафіксувати індекс" або як викачати дані з частково відновленої (неузгодженої) бази даних

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 попередить вас і надасть список таких обмежень - одне або кілька з них слід видалити, перш ніж перекачування стане доступним.

Звичайно, були випадки, коли перекачування вимагало особливого підходу, і якщо ви зіткнетеся з такою ситуацією, будь ласка, зверніться до нашої підтримки.