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

Бібліотека IBSurgeon

Посібник з відновлення InterBase та Firebird

NOTICE: This document is the chapter from the book “The InterBase World” which was written by Alexey Kovyazin and Serg Vostrikov.

Розділ з книги «The InterBase World», присвячений відновленню баз даних.

1. Історія цього посібника

Російська книга «The InterBase World» була опублікована у вересні 2002 року.

Її наклад становив 3000 примірників. Через 3 місяці вона була розпродана, і у квітні 2003 року було опубліковано друге, покращене видання накладом 5000 примірників.

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

Авторами книги є Олексій Ковязін, розробник IBSurgeon та

відомий російський спеціаліст з InterBase, і Серг Востріков, генеральний директор компанії Devrace www.devrace.com

Цікаво, що жодної книги, присвяченої InterBase, не було опубліковано англійською мовою!

Тисячі й тисячі розробників використовують InterBase та Firebird, обговорюють цю тему в різних конференціях (подивіться тут: Links).

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

Ми можемо посперечатися на ящик пива, що наклад у 10000 примірників буде зметено з Amazon.com за місяць. Але люди у видавничих компаніях «знають усе» і впевнені, що ніхто не купуватиме книгу про InterBase. Це справжня шкода.

Тут ми хотіли б запропонувати вам чернетку одного розділу цієї книги, присвяченого відновленню баз даних InterBase/Firebird.

2. Як відновити базу даних InterBase/Firebird

2.1. Огляд основних причин пошкодження бази даних

На жаль, завжди існує ймовірність того, що будь-яке сховище інформації буде пошкоджено і частина інформації з нього буде втрачена. База даних не є винятком із цього правила. У цьому розділі ми розглянемо основні причини, що призводять до пошкодження бази даних InterBase, деякі методи відновлення баз даних та вилучення інформації з них. Також ми ознайомимося з рекомендаціями та запобіжними заходами, які мінімізують ймовірність втрати інформації з бази даних.

Перш за все, якщо ми говоримо про відновлення бази даних, слід уточнити поняття «пошкодження бази даних». База даних зазвичай називається пошкодженою, якщо під час спроби вилучити або змінити певну інформацію виникають помилки та/або вилучена інформація виявляється втраченою, неповною або зовсім неправильною. Існують випадки, коли пошкодження бази даних є прихованими і виявляються лише під час тестування спеціальними засобами, але також існують реальні пошкодження бази даних, коли неможливо підключитися до бази даних, коли налаштовані програми-клієнти показують дивні помилки (коли жодних маніпуляцій із базою даних не виконувалося), або коли неможливо відновити базу даних із резервної копії.

2.2. Основними причинами пошкодження бази даних є:

  • Аварійне завершення роботи серверного комп’ютера, особливо переривання електропостачання. Для ІТ-індустрії це справжнє лихо, і тому ми сподіваємося, що немає потреби ще раз нагадувати про необхідність наявності джерела безперебійного живлення на сервері.
  • Дефекти та несправності серверного комп’ютера, особливо HDD (жорсткого диска), контролерів дисків, основної пам’яті комп’ютера та кеш-пам’яті RAID-контролерів.
  • Неправильний рядок підключення до багатоклієнтської бази даних одного або кількох користувачів (у версіях до 6.x). Під час підключення через TCP/IP шлях до бази даних має вказувати ім’я сервера: диск:/шлях/ім’я_бази_даних (для серверів на платформі UNIX ім’я_сервера: /шлях/ім’я_бази_даних), згідно з протоколом NETBEUI \\ім’я_сервера\диск:\шлях\ім’я_бази_даних. Навіть під час підключення до бази даних з комп’ютера, на якому розташована база даних і працює сервер, слід використовувати той самий рядок, замінюючи ім’я сервера на localhost. Не можна використовувати мережевий диск у рядку підключення. Якщо порушити одне з цих правил, сервер вважає, що працює з різними базами даних, і пошкодження бази даних гарантоване.
  • Копіювання файлу або інший доступ до файлу бази даних, коли сервер працює. Виконання команди «shut-down» або відключення користувачів звичайним способом не є гарантією того, що сервер нічого не робить із базою даних, якщо інтервал sweep не встановлено на «0», може виконуватися збір сміття. Зазвичай збір сміття виконується одразу після відключення останнього користувача від бази даних. Зазвичай це займає кілька секунд, але якщо до цього було зафіксовано багато операцій DELETE або UPDATE, процес може тривати довше.
  • Використання нестабільних версій сервера InterBase 5.1-5.5. Компанія Borland офіційно визнала, що в цих серверах було кілька помилок, і стабільне оновлення 5.6 було видалено лише після виходу сертифікованого InterBase 6 у вільному режимі для всіх клієнтів серверів 5.1-5.5 на її сайті.
  • Перевищення обмеження розміру файлу бази даних (не бази даних!). Для версій до InterBase 6 та деяких бета-версій InterBase 6 ліміт файлу бази даних становить 4 ГБ, для InterBase 6.5 та всіх випусків Firebird (1.0, 1.5, 2.0, 2.1) - 32 ТБ. При наближенні розміру бази даних до граничного значення необхідно створити додатковий файл.
  • Вичерпання вільного місця на диску під час роботи з базою даних.
  • Для серверів Borland InterBase версій нижче 6.0.1.6 - перевищення обмеження на кількість генераторів, визначеного відділом досліджень і розробок Borland InterBase наступним чином (дивіться таблицю 1).
Версія Розмір сторінки=1024 Розмір сторінки=2048 Розмір сторінки=4096 Розмір сторінки=8192
До 6 248 504 1016 2040
6.0.x 124 257 508 102

Таблиця 1: Критична кількість генераторів у ранніх версіях InterBase

• Для всіх серверів Borland InterBase - перевищення допустимої кількості транзакцій без виконання резервного копіювання/відновлення. Дізнатися кількість транзакцій, що відбулися в базі даних з моменту останнього створення, можна, викликавши утиліту gstat з ключем - h - параметр NEXT TRANSACTION ID буде бажаною кількістю транзакцій. Згідно з Енн В. Гаррісон, критична кількість транзакцій залежить від розміру сторінки і має такі значення (дивіться таблицю 2):

Розмір сторінки бази даних Критична кількість транзакцій
1024 байти 131 596 287
2048 байтів 265 814 016
4096 байтів 534 249 472
8192 байти 1 071 120 384

Таблиця 2: Критична кількість транзакцій у серверах Borland InterBase

Обмеження серверів Borland InterBase, перелічені вище, не застосовуються до серверів Firebird, за винятком найраніших версій 0.x, існування яких уже стало історією. Якщо ви використовуєте фінальну версію Firebird 1.0 або InterBase 6.5-7.x, вам не варто турбуватися про пункти 5, 6, 8 і 9, і ви повинні зосередити свої зусилля на інших причинах. Тепер ми розглянемо найчастіші з них детально.

2.3. Збій електропостачання

При вимкненні живлення на сервері всі операції з обробки даних перериваються в найнесподіваніших і (згідно із законом Мерфі) найнебезпечніших місцях. У результаті цього інформація в базі даних може бути спотворена або втрачена. Найпростіший випадок - коли всі незафіксовані дані з клієнтських застосунків були втрачені внаслідок аварійного завершення роботи сервера. Після перезапуску після збою живлення сервер аналізує дані, помічає незавершені транзакції, що не належать жодному з клієнтів, і скасовує всі зміни, зроблені в межах цих «мертвих» транзакцій. Власне, така поведінка є нормальною і передбаченою розробниками InterBase з самого початку.

Однак переривання електропостачання не завжди супроводжується лише такими незначними втратами. Якщо сервер виконував розширення бази даних у момент переривання електропостачання, існує велика ймовірність появи «осиротілих» сторінок у файлі бази даних (сторінок, які фізично виділені та зареєстровані на сторінці інвентаризації сторінок (PIP), запис даних на які неможливий). Якщо ви хочете дізнатися більше про «осиротілі» сторінки, перегляньте розділ «Структура бази даних InterBase».

Лише інструмент відновлення та модифікації gfix (ми розглянемо його нижче) здатний боротися з «осиротілими» сторінками у файлі бази даних. Власне, «осиротілі» сторінки призводять до зайвих витрат дискового простору і як такі не є причиною втрати даних або пошкодження.

Втрата живлення призводить до серйозніших пошкоджень. Наприклад, після вимкнення живлення та перезапуску може бути втрачено велику кількість даних, включаючи підтверджені (після додавання або модифікації яких було виконано команду «commit transaction»). Це відбувається тому, що підтверджені дані не записуються безпосередньо у файл бази даних на диску. Для цієї мети використовується файловий кеш операційної системи (ОС). Процес сервера надіслав командy запису даних до ОС. Потім ОС запевнила сервер, що всі дані збережено на диску, а насправді дані зберігалися у файловому кеші. ОС не поспішає скидати ці дані на диск, оскільки вважає, що в основній пам’яті ще багато вільного місця, і відкладає повільні операції запису на диск до заповнення основної пам’яті.

2.4. Примусові записи - палиця з двома кінцями

Щоб вплинути на ситуацію, в InterBase 6 передбачено налаштування режиму запису даних. Цей параметр називається forced writes (FW) і має 2 режими - ON (синхронний) та OFF (асинхронний). Режими FW визначають, як InterBase взаємодіє з диском. Якщо FW увімкнено, вмикається налаштування синхронного запису на диск, коли підтверджені дані записуються на диск одразу після команди commit, сервер чекає завершення запису і лише потім продовжує обробку. Якщо FW вимкнено, InterBase не поспішає записувати дані на диск після команди фіксації транзакції та делегує це завдання паралельному потоку, тоді як головний потік продовжує обробку даних, не чекаючи завершення записів на диск. Режим синхронного запису є одним із найобережніших і мінімізує будь-які можливі втрати даних, однак може спричинити деяку втрату продуктивності. Режим асинхронного запису збільшує ймовірність втрати великої кількості даних. Для досягнення максимальної продуктивності зазвичай встановлюють режим FW Off. Але в результаті переривання живлення під час асинхронного запису втрачається набагато більше даних, ніж під час синхронного. Встановлюючи режим запису, слід вирішити, чи є кілька відсотків продуктивності важливішими за кілька годин роботи, якщо раптово станеться переривання живлення.

Дуже часто користувачі недбало ставляться до InterBase. Малі організації економлять на будь-якій дрібниці, часто на комп’ютері-сервері, де встановлено СКБД-сервер та різні серверні програми (і не лише серверні). Якщо вони зависають, люди, недовго думаючи, натискають RESET (це трапляється кілька разів на день). Хоча InterBase дуже стійкий до таких дій порівняно з іншими СКБД і дозволяє почати роботу з базою даних одразу після аварійного перезавантаження, таке використання небажане. Кількість осиротілих сторінок збільшується, і дані втрачають зв’язок між собою в результаті аварійних перезавантажень.

Це може тривати довго, але рано чи пізно все закінчиться. Коли серед сторінок PIP або сторінок генераторів з’являються пошкоджені сторінки, або якщо пошкоджено сторінку заголовка бази даних, база даних може ніколи більше не відкритися і перетворитися на великий шматок окремих даних, з яких неможливо витягти жодного байта корисної інформації.

2.5. Пошкодження жорсткого диска

Пошкодження жорсткого диска призводять до зникнення важливих системних сторінок бази даних та/або пошкодження зв’язків між сторінками, що залишилися. Такі пошкодження є одними з найскладніших випадків, оскільки майже завжди вимагають втручання на низькому рівні для відновлення бази даних.

2.6. Помилки проєктування бази даних

Необхідно знати про деякі помилки, які допускають розробники баз даних і які можуть призвести до неможливості відновлення бази даних із резервної копії (файлів *.gbk, створених програмою gbak). Перш за все, це необережне використання обмежень на рівні бази даних. Типовим прикладом є обмеження NOT NULL. Припустімо, що ми маємо таблицю, заповнену певною кількістю записів. Тепер ми додамо до цієї таблиці за допомогою команди ALTER TABLE ще одну колонку і вкажемо, що вона не повинна містити невизначених значень NULL. Щось на кшталт цього:

ALTER TABLE sometable Field/INTEGER NOT NULL

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

Однак, якщо ми створимо резервну копію бази даних і спробуємо відновити її з резервної копії, ми отримаємо повідомлення про помилку на етапі відновлення (оскільки NULL вставляються в колонку з обмеженням NOT NULL, і процес відновлення буде перервано. (Важлива примітка від Craig Stuntz - у версії InterBase 7.1 обмеження за замовчуванням ігноруються під час відновлення (це можна контролювати за допомогою параметра командного рядка), і майже будь-яку непошкоджену резервну копію можна відновити. Завжди корисно виконувати тестове відновлення після створення резервної копії, але ця проблема має практично зникнути у версії 7.1.) Цю резервну копію неможливо відновити. Якщо відновлення було спрямоване на файл з тим самим іменем, що й існуюча база даних (під час відновлення робочий файл існуючої бази даних перезаписувався), ми втратимо всю інформацію.

Це пов’язано з тим, що обмеження NOT NULL реалізовані системними тригерами, які перевіряють лише вхідні дані. Під час відновлення дані з резервної копії вставляються в порожні щойно створені таблиці - тут ми можемо виявити неприпустимі NULL у колонці з обмеженням NOT NULL.

Деякі розробники вважають таку поведінку InterBase неправильною, але інший не зможе додати поле з обмеженням NOT NULL до таблиці бази даних.

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

Подібну проблему може спричинити збій збирання сміття через встановлення неправильного шляху до бази даних (причина пошкодження 3) під час підключення та доступу до файлів бази даних, коли сервер працює з нею (причина пошкодження 4), і записи, повністю заповнені Null, можуть з’явитися в деяких таблицях. Дуже важко виявити ці записи, оскільки вони не відповідають обмеженням контролю цілісності, а оператор Select просто їх не бачить, хоча вони потрапляють у резервну копію. Якщо з цієї причини відновлення неможливе, слід запустити програму gfix (див. нижче), знайти та видалити ці записи, використовуючи неіндексовані поля як умови пошуку, після чого повторити спробу створення резервної копії та відновлення бази даних з неї. На завершення можна сказати, що існує велика кількість причин пошкодження бази даних, і ви завжди повинні бути готові до найгіршого - що ваша база даних буде пошкоджена з тієї чи іншої причини. Ви також повинні бути готові відновити та зберегти цінну інформацію. А тепер розглянемо запобіжні заходи, які гарантують безпеку бази даних InterBase, а також методи відновлення пошкоджених баз даних.

2.7. Запобіжні заходи від пошкодження бази даних InterBase

Щоб запобігти пошкодженню бази даних, слід завжди створювати резервні копії (якщо ви хочете дізнатися більше про резервне копіювання, перегляньте розділ «Резервне копіювання та відновлення»). Це найнадійніший спосіб захисту від пошкодження бази даних. Лише резервна копія дає 100% гарантію безпеки бази даних. Як описано вище, в результаті резервного копіювання ми можемо отримати марну копію (копію, яку неможливо відновити), тому відновлення бази з копії не повинно виконуватися шляхом перезапису сценарію, а резервне копіювання має виконуватися за певними правилами. По-перше, резервне копіювання має виконуватися якомога частіше, по-друге, воно має бути послідовним, і по-третє, резервні копії мають перевірятися на можливість відновлення.

Часто резервне копіювання означає, що необхідно створювати резервну копію досить часто, наприклад, раз на двадцять чотири години. Чим менший період між резервним копіюванням бази даних, тим менше даних буде втрачено в результаті збою. Послідовність резервного копіювання означає, що кількість резервних копій має збільшуватися і зберігатися принаймні протягом тижня. Якщо є можливість, необхідно записувати резервні копії на спеціальні пристрої, наприклад стример, а якщо ні - просто копіювати їх на інший комп’ютер. Історія резервних копій допоможе виявити приховані пошкодження та впоратися з помилкою, яка виникла давно і проявилася несподівано. Потрібно перевіряти, чи можна відновити отриману резервну копію без помилок чи ні. Це можна перевірити лише одним способом - через процес тестового відновлення. Слід зазначити, що процес відновлення займає в 3 рази більше часу, ніж резервне копіювання, і виконувати перевірку відновлення щодня для великих баз даних складно, оскільки це може перервати роботу користувачів на кілька годин (нічного перерви може бути недостатньо).

Було б краще, якби великі організації не економили на «запасних» комп’ютерах і залишали одну машину для цих цілей.

У цьому випадку, якщо сервер має працювати з серйозним навантаженням 24 години 7 днів на тиждень, ми можемо використати механізм SHADOW для створення знімків бази даних і подальших операцій резервного копіювання з безпосередньої копії. Процес резервного копіювання та відновлення бази даних детально описано в розділі «Резервне копіювання та відновлення». Під час створення резервної копії та подальшого відновлення бази даних з неї відбувається відтворення всіх даних у базі. Цей процес (резервне копіювання/відновлення або б/в) сприяє виправленню більшості нефатальних помилок у базі даних, пов’язаних із пошкодженням жорсткого диска, виявленню проблем із цілісністю бази даних, очищенню бази від сміття (старих версій і фрагментів записів, незавершених транзакцій), значному зменшенню розміру бази даних.

Регулярне б/в є гарантією безпеки бази даних InterBase. Якщо база даних працює, рекомендується виконувати б/в щотижня. Щоправда, існують приклади баз даних InterBase, які інтенсивно використовувалися протягом багатьох років без резервного копіювання/відновлення.

Тим не менш, щоб бути в безпеці, бажано виконувати цю процедуру, особливо тому, що її легко автоматизувати (див. розділ «Резервне копіювання»).

Якщо з якихось причин неможливо часто виконувати резервне копіювання/відновлення, можна скористатися інструментом gfix для перевірки та відновлення бази даних. gfix дозволяє перевірити та усунути багато помилок без б/в.

2.8. Інструмент командного рядка gfix

Інструмент командного рядка gfix використовується для перевірки та відновлення бази даних. Крім того, gfix може виконувати різні дії з керування базою даних: зміну діалекту бази даних, встановлення та скасування режиму «тільки для читання», встановлення розміру кешу для конкретної бази даних, а також деякі важливі функції (про них можна дізнатися в InterBase 6 Operations Guide [4.). gfix запускається в режимі командного рядка і має наступний синтаксис:

Gfix [ параметри] ім’я_бд

Параметри - це набір опцій для виконання gfix, ім’я_бд - це назва бази даних, над якою будуть виконуватися операції, визначені набором опцій. Таблиця 3 представляє опції gfix, пов’язані з відновленням бази даних:

Опція Опис
-f[ull] Ця опція використовується в поєднанні з -v і
означає, що настав час перевірити всі фрагменти записів
-i[gnore] Опція змушує gfix ігнорувати помилки контрольних сум під
час перевірки або очищення бази даних
-m[end] Позначає пошкоджені записи як недоступні, в
результаті чого вони будуть видалені під час
наступного резервного копіювання/відновлення. Опція використовується під
час підготовки пошкодженої бази даних до б/в.
-n[o_update] Опція використовується в поєднанні з -v для
перевірки бази даних лише для читання без виправлення
пошкоджень
-pas[sword] Опція дозволяє встановити пароль під час
підключення до бази даних. (Зверніть увагу, що це помилка в
документації InterBase -pa[ssword], але скорочення
«-pa» не працюватиме - використовуйте «-pas»)
-user Опція дозволяє встановити ім’я користувача для підключення
до бази даних
-v[alidate] Опція, що встановлює перевірку бази даних, у
процесі якої виявляються помилки
-m[ode] Опція, що встановлює режим запису для бази даних - лише
для читання або читання/запис. Цей параметр може
приймати 2 значення - read write або read only.
-w[rite] {sync | async} Опція, що вмикає та вимикає режим
синхронного/асинхронного примусового запису до
бази даних. sync - увімкнути синхронний запис
(FW ON); async - увімкнути асинхронний запис
(FW OFF);

Таблиця 1: Опції інструменту gfix для відновлення бази даних

Існують деякі типові приклади використання gfix:

gfix -w sync -user SYSDBA -pass masterkey firstbase.gdb

У цьому прикладі ми встановлюємо для нашої тестової бази даних firstbase.gdb режим синхронного запису (FW ON). (Звичайно, це корисно зробити до виникнення пошкодження). А нижче наведено першу команду, яку слід використовувати для перевірки бази даних після виникнення пошкодження:

gfix -v -full -user SYSDBA -pass masterkey firstbase.gdb

У цьому прикладі ми запускаємо перевірку нашої тестової бази даних (опція -v) і вказуємо, що фрагменти записів також мають бути перевірені (опція -full). Звичайно, зручніше встановлювати різні опції для процесу перевірки та відновлення за допомогою будь-якого графічного інтерфейсу, але ми розглянемо функції відновлення бази даних за допомогою інструментів командного рядка. Ці інструменти входять до складу InterBase, і ви можете бути впевнені, що їх поведінка буде однаковою на всіх ОС, що працюють з InterBase. Дуже важливо, щоб вони завжди були поруч.

Крім того, існуючі інструменти, що дозволяють виконувати адміністрування бази даних з клієнтського комп’ютера, використовують для цього Services API, який не підтримується архітектурою сервера InterBase Classic. Це означає, що ви можете використовувати сторонні продукти з архітектурою сервера SuperServer.

2.9. Відновлення пошкодженої бази даних

Припустимо, що в нашій базі даних є деякі помилки. По-перше, ми маємо перевірити наявність цих помилок; по-друге, ми маємо спробувати виправити ці помилки. Слід дотримуватися наступних інструкцій.

Слід зупинити сервер InterBase, якщо він ще працює, і зробити копію файлу або файлів бази даних. Усі дії з відновлення слід виконувати лише з копією бази даних, оскільки обраний спосіб може призвести до небажаного результату, і вам доведеться розпочинати процедуру відновлення заново (з початкової точки). Після створення копії ми виконаємо повну перевірку бази даних (перевірку фрагментів записів).

Для цього слід виконати наступну команду:

gfix -v - full corruptbase gdb -user SYSDBA - password

У цьому випадку corruptbase.gdb - це копія пошкодженої бази даних. Команда перевірить базу даних на наявність будь-яких структурних пошкоджень і надасть список невирішених проблем. Якщо такі помилки виявлено, нам доведеться видалити пошкоджені дані та підготуватися до резервного копіювання/відновлення за допомогою наступної команди:

gfix -mend -user SYSDBA -password your_masterkey corruptbase gdb

Після виконання команди слід перевірити, чи залишилися помилки в базі даних. Для цього потрібно запустити gfix з опціями -v -full, а коли процес завершиться, виконати резервне копіювання бази даних:

gbak -b -v -ig -user SYSDBA -password corruptbase.gdb corruptbase.gbk

Ця команда виконає резервне копіювання бази даних (про це свідчить опція - b), і ми отримаємо детальну інформацію про процес виконання резервного копіювання (опція -v). Помилки щодо контрольних сум будуть проігноровані (опція - ig). Якщо ви хочете дізнатися більше про опції інструменту командного рядка gbak, ви можете знайти це в розділі «Резервне копіювання та відновлення». Якщо під час резервного копіювання виникають помилки, слід запустити його в іншій конфігурації:

gbak -b -v -ig -g -user SYSDBA -password corruptbase.gdb

corruptbase.gbk

Де опція - g вимкне збір сміття під час резервного копіювання. Це часто допомагає вирішити проблему з резервним копіюванням.

Також можливо виконати резервне копіювання бази даних, якщо перед цим встановити базу даних у режим лише для читання. Цей режим запобігає запису будь-яких змін до бази даних і іноді допомагає виконати резервне копіювання пошкодженої бази даних. Для встановлення бази даних у режим лише для читання слід використати наступну команду: gfix -m read _only

-user SYSDBA -password masterkey Disk:\Path\file.gdb

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

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

gbak -c -user SYSDBA -password masterkey Disk:\Path\backup.gbk

Disk:\Path\newbase,gdb

Під час відновлення бази даних можуть виникнути деякі проблеми, особливо під час створення індексів. У цьому випадку до команди відновлення слід додати опції -inactive та -one_at_a_time. Ці опції деактивують індекси, що створюються з резервної копії бази даних, і підтверджують дані для кожної таблиці окремо.

2.10. Як можна спробувати витягти дані з пошкодженої бази даних

Можливо, що операції, наведені вище, не призведуть до відновлення бази даних.

Це означає, що база даних серйозно пошкоджена, або її неможливо відновити як єдине

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

Отже, перед перенесенням даних зі старої бази даних необхідно створити базу призначення. Якщо база даних не змінювалася протягом тривалого часу, можна використати стару резервну копію, з якої можна витягти метадані для створення бази призначення. На основі цих метаданих потрібно створити базу призначення і почати копіювання даних. Головне завдання - витягти дані з пошкодженої бази даних. Потім нам доведеться розмістити дані в новій базі, але це не дуже складно, навіть якщо доведеться відновлювати структуру бази даних з пам’яті. Під час витягування даних з таблиць слід використовувати наступний алгоритм операцій:

  • Спочатку слід спробувати виконати SELECT* з таблиці N. Якщо це пройшло нормально, ви можете зберегти отримані дані у зовнішньому джерелі. Краще зберігати дані у скрипті (майже всі GUI надають цю функцію), якщо тільки таблиця не містить BLOB-полів. Якщо в таблиці є BLOB-поля, то дані з них слід зберегти в іншу базу даних за допомогою клієнтської програми, яка відіграватиме роль посередника. Можливо, вам доведеться написати цю тривіальну програму спеціально для цілей відновлення даних.
  • Якщо вам не вдалося отримати всі дані, слід видалити всі індекси і спробувати ще раз. Фактично, індекси можна видалити з усіх таблиць з самого початку відновлення, оскільки вони більше не знадобляться. Звичайно, якщо у вас немає структури метаданих, ідентичної пошкодженій, необхідно вести протокол усіх операцій, які ви виконуєте з пошкодженою базою-джерелом.
  • Якщо вам не вдається прочитати всі дані з таблиці після видалення індексів, можна спробувати виконати діапазонний запит за первинним ключем. Це означає вибір певного діапазону даних. Наприклад:

SELECT * FROM table N WHERE field_PK >=0 and field_PK <=10000 Field_PK

тут - первинний ключ. InterBase має посторінкову організацію даних, і тому діапазонний запит значень може бути досить ефективним, хоча це виглядає як щось на кшталт шаманізму. Тим не менш, це працює, тому що ми можемо виключити дані з пошкоджених сторінок і, на щастя, прочитати інші. Ви можете згадати наш тезис про те, що в SQL не існує визначеного порядку зберігання записів. Насправді ніхто не гарантує, що невпорядкований запит під час перезапусків поверне записи в тому самому порядку, але тим не менш фізичні записи зберігаються в базі даних у визначеному внутрішньому порядку. Очевидно, що сервер не перемішуватиме записи лише для дотримання стандарту SQL. Можна спробувати використати цей внутрішній порядок для витягування даних з пошкодженої бази даних (якщо ви хочете дізнатися більше про сторінки даних та їхні зв’язки, зверніться до розділу «Структура бази даних InterBase»).

Віталій Бармін, один із досвідчених російських розробників InterBase, повідомив, що таким чином йому вдалося відновити до 98% інформації з непіддатливої відновленню бази даних (там була велика кількість пошкоджених сторінок). Таким чином, дані з пошкодженої бази даних необхідно перенести в нову базу даних або у зовнішні джерела, як-от SQL-скрипти. Під час копіювання даних зверніть увагу на значення генераторів у пошкодженій базі даних (їх необхідно зберегти для відновлення належної роботи в новій базі даних. Якщо у вас немає повної копії метаданих, слід витягти тексти збережених процедур, тригерів, обмежень та визначення індексів.

2.11. Відновлення безнадійної бази даних

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

Перший випадок (класична проблема). Резервна копія, яку неможливо відновити через наявність NULL-значень у стовпці з обмеженням NOT NULL (процес відновлення виконувався над робочим файлом). Робочий файл було стерто, і процес відновлення було перервано через помилку. І в результаті необдуманих дій ми отримали велику кількість марних даних (які неможливо відновити) замість резервної копії. Але рішення було знайдено. Програмісту вдалося згадати, яка таблиця та який стовпець мали обмеження NOT NULL. Файл резервної копії було завантажено в шістнадцятковий редактор. І комбінацію байтів, що відповідала визначенню цього стовпця, було знайдено там шляхом пошуку. Після незліченних експериментів виявилося, що обмеження NOT NULL додає 1 десь біля назви стовпця. У HEX-редакторі цю «1» було виправлено на «0», і резервну копію було відновлено. Після цього випадку програміст запам’ятав раз і назавжди, як виконувати процес резервного копіювання та відновлення.

Другий випадок. Ситуація була катастрофічною. База даних пошкодилася на етапі розширення через брак дискового простору. Під час збільшення розміру бази даних сервер створює серію критично важливих сторінок (наприклад, сторінку інвентаризації транзакцій і сторінку інвентаризації сторінок, додаткові сторінки для зв’язку RDB$Pages) і записує їх у кінець бази даних. У результаті база даних не відкривалася ні засобами адміністрування, ні утилітою GBAK. І коли ми спробували підключитися до бази даних, з’явилося повідомлення про помилку («Unexpected end of file»).

Коли ми запустили утиліту gfix, відбувалися дивні речі: програма працювала в нескінченному циклі. Поки працював gfix, сервер записував помилки до журналу (файл InterBase log) з високою швидкістю (близько 100 Кб на секунду). У результаті файл журналу дуже швидко заповнив весь вільний дисковий простір. Нам навіть довелося написати програму, яка стирала цей журнал за таймером. Цей процес тривав довго - gfix працював понад 16 годин без жодних результатів. Журнал був заповнений помилками такого вигляду: «Page XXX doubly allocated». У вихідних кодах InterBase (у файлі val.#) є короткий опис цієї помилки. Там сказано, що ця помилка з’являється, коли одна й та сама сторінка даних використовується двічі. Очевидно, що ця помилка є результатом пошкодження критично важливих сторінок.

У результаті після кількох днів невдалих експериментів спроби відновити дані стандартними способами були залишені. І тому нам довелося використати низькорівневий аналіз даних, що зберігаються в пошкодженій базі даних.

Олександр Козельський, начальник відділу інформаційних технологій East View Publications Inc, є автором ідеї витягування інформації з подібних непіддатливих відновленню баз даних.

Метод відновлення, який ми отримали в результаті досліджень, ґрунтувався на тому факті, що база даних має посторінкову організацію, і дані з кожної таблиці збираються на сторінках даних. Кожна сторінка даних містить ідентифікатор таблиці, для якої вона зберігає дані. Особливо важливо було відновити дані з кількох критичних таблиць. Там були дані з подібних таблиць, отримані зі старої резервної копії, яка чудово працювала і могла бути зразком. Базу-зразок було завантажено в редактор шістнадцяткових джерел, і потім ми шукали зразки тих даних, які нас цікавили. Ці дані було скопійовано в буфер у шістнадцятковому форматі, а потім залишки пошкодженої бази даних було завантажено в редактор. Послідовність байтів, що відповідала зразку, було знайдено в пошкодженій базі даних, і сторінку (на якій було знайдено цю послідовність) було проаналізовано.

Спочатку ми визначили початкову сторінку, але це було не складно, оскільки розмір файлу бази даних ділиться на розмір сторінки даних. Номер поточного байта, поділений на розмір сторінки - 8192 байти, округлює результат до цілого числа (і ми отримали номер поточної сторінки). Потім помножили номер поточної сторінки на розмір сторінки і отримали номер байта, що відповідає початку поточної сторінки. Проаналізувавши заголовок, ми визначили тип сторінки (для сторінок з даними тип - 5 - дивіться файл ods.h із набору вихідних кодів InterBase, а також розділ «Структура бази даних InterBase»), а також ідентифікатор необхідної таблиці.

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

Таким чином, коли ми отримали потрібні дані на першому етапі, ми почали аналізувати вміст вибраних сторінок. InterBase широко використовує стиснення даних для економії місця. Наприклад, рядок типу VARCHAR, що містить рядок «ABC», зберігає послідовність таких значень: довжина рядка (2 байти), у нашому випадку це 0003, потім самі символи, а далі контрольна сума. Нам довелося написати аналізатор рядків, а також інших типів даних бази, який перетворював дані з шістнадцяткового формату у звичайний вигляд. Нам вдалося витягти до 80% інформації з кількох критичних таблиць за допомогою «ручного» методу аналізу вмісту бази даних. Пізніше, на основі цього досвіду, Олег Кульков та Олексій Ковязін, один із авторів цієї книги, розробили утиліту InterBase Surgeon, яка виконує прямий доступ до бази даних, оминаючи рушій InterBase, і дозволяє безпосередньо читати та правильно інтерпретувати дані в базі даних InterBase.

Використовуючи InterBase Surgeon, нам вдалося виявити причини пошкоджень і відновити до 90% абсолютно невідновлюваних баз даних, які не можуть бути відкриті InterBase та відновлені стандартними методами.

Ви можете завантажити цю програму з офіційного сайту програми www.ib-aid.com.

3. Подяки

Я хотів би висловити подяку всім, хто допоміг мені створити цей посібник:

Крейг Стунц, Олександр Невський, Костянтин Сіпачов, Тетяна Сіпачова та всі інші добрі та обізнані люди зі спільноти InterBase та Firebird.

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

© 2002 Олексій Ковязін, Сергій Востріков.

Copyright © 2004 IBSurgeon Team. Всі права захищені.