Když vaše data udělají Puf...

24. 1. 2012 11:46 (aktualizováno) Pavel Císař

…a zmizí v propadlišti dějin, nemusí být ještě vše ztraceno.

Pokud máte (alespoň relativně čerstvou) zálohu, není co řešit. Pokud ji ale nemáte, a používáte InterBase nebo Firebird, zavoláte nám, nebo do společnosti IBSurgeon. Sice v tom již pár měsíců není žádný rozdíl, ale to je vcelku podřadný detail. Důležité je, že máte komu zavolat. A právě to se stalo minulý týden, zrovna když jsem se chystal vrhnout střemhlav do psaní testů pro Firebird. Člověk míní, a život mění.

V tomto konkrétním případě šlo o nedopatřením dropnutou tabulku s zhruba 400 000 záznamy. Třešničkou na dortu pak byla skutečnost, že databáze pocházela z obstarožní InterBase 5.6. Naštěstí máme verzi 5.6 v archivu (stejně jako mnoho dalších verzí) i s licencemi.

Pokud si svůj omyl uvědomíte včas a databázi okamžitě odstavíte, máte v případě nešťastného výmazu dat (ať už příkazem DROP TABLE nebo DELETE FROM) velmi dobrou šanci dostat všechna svá data zpět. V obou případech vám pomůže nástroj IBUndelete, který v případě zrušené tabulky nasadíte na obnovu dat v systémových tabulkách, v případě zrušených dat na inkriminovanou tabulku. IBUndelete je malý zázrak, a značně zredukoval počet požadavků na obnovu nedopatřením smazaných dat které musíme řešit.

IBUndelete vám ovšem moc nepomůže pokud máte takovou smůlu, že zrušené záznamy již prošly mlýnicí zvanou Garbage Collection, ale i v takových případech jsme většinou schopni konat zázraky, a data rekonstruovat ručně. V databázi kterou jsem dostal na stůl ovšem byla tabulka nejen zrušena, ale místo ní byla vytvořena tabulka jiná, stejného jména ale s jinou strukturou (Paradox je potvora). Netřeba snad zdůrazňovat, že IBUndelete si v tomto případě ani neškrtnul, protože metadata nebyla jen zrušena, ale nenávratně přemazána novou definicí. Samotná data naštěstí zůstala netknutá (až na jedinou datovou stránku), takže jejich obnova by sice nebyla „triviální“, ale rozhodně proveditelná. Obnášelo by to jen nepříjemné množství zdlouhavé „ruční práce“, a protože jsem měl v plánu psát testy pro Firebird, byla moje první reakce přenechat databázi kolegům. Bohužel jsem zjistil, že všichni naši specialisté na obnovu dat již mají plné ruce práce s jinou databází rozstřílenou na mraky, takže jsem se do obnovy s chutí pustil sám. S opravou databází už mám nějaké ty zkušenosti a navíc je to občas i zábava (tedy pokud považujete za zábavné skládat puzzle jehož kousky jsou poschovávané na hektaru vzrostlého lesa).

V případech jako je tento jsou v principu dva způsoby jak postupovat. Jednak se můžete pokusit kompletně rekonstruovat původní metadata uložená v systémových tabulkách a pomocí nízkoúrovňových vazeb uvnitř databáze, a zpřístupnit tak data běžnými prostředky, druhak můžete napsat program který najde a vyzobe kousky dat z databáze, dekóduje je a uloží v použitelném tvaru. První postup je velice komplexní, pracný a neskýtá 100% záruku na úspěch. Navíc dokud neprovedete všechny potřebné kroky, nebudete vědět zda jste uspěli nebo jen vyplýtvali spoustu času a energie na objevení slepé uličky. Druhý postup je ještě 100× komplexnější a pracnější než první, ale stoprocentně spolehlivý. Důvod, proč je druhý postup náročnejší spočívá v tom, že
musíte v podstatě vytvořit (a odladit) specifickou verzi ořezaného Firebirdu se „zadrátovanými“ metadaty obnovovaných dat, které mohou být i v několika různých formátech pokud jste na živé databázi prováděli úpravu struktury tabulek (což naštěstí nebyl tento případ). V prvním případě už tuto aplikaci máte (Firebird), jde jen o to, poskytnout jí správné pracovní parametry (metadata). Vzhledem k blížícím se Velikonočním svátkům jsem se rozhodl nejprve vyzkoušet první postup, který přeci jen skytá šanci na „rychlý“ úspěch.

Na rekonstrukci metadat uložených v systémových tabulkách je nejlepší použít přímo databázový server (pracovat „ručně“ na úrovni jednotlivých řádků tabulek by jste určitě nechtěli). Zapisovat serverem do metadat zachraňované databáze ovšem není nejlepší nápad, proto se používá technika zvaná „transplantace“. Postup je jednoduchý. Vytvoříte prázdnou databázi se shodnou strukturou (nebo částí struktury) jako zachraňovaná databáze (a to včetně sledu modifikací struktury tabulek, ke kterým případně došlo), a přenesete (čili transplantujete) jednotlivé databázové stránky (v tomto případě stránky obsahující data vybraných systémových tabulek) ze „zdravé“ databáze do databáze poškozené. Přenos stránek ale ve většině případů není prosté kopírování stejných bloků z jednoho souboru do druhého (takové případy jsou vzácné), protože obě databáze nejsou na fyzické úrovni zcela totožné. Musíte tedy najít ty správné stránky v jedné databázi, a najít to správné místo pro zápis každé jedné z nich v druhé databázi. Po transplantaci je nutné ještě upravit data na některých stránkách, upravit vazby mezi stránkami, upravit data v tabulce RDB$PAGES, zrušit indexy na modifikovaných systémových tabulkách (což není tak triviální jak se může zdát) a upravit katalog alokace stránek. Protože konkrétní postup je u každé databáze vždy jiný, napsal jsem si před časem knihovnu pomocných tříd (v Object Pascalu) pro nízkoúrovňovou práci s databázemi, a vytvářím si jednorázové nástroje dle potřeby (v Delphi 7 mi to jde pořád rychleji než v Céčku, obzvláště když životnost takového nástroje je jen pár hodin nebo minut). Pokud máte zájem podívat se jak to vypadá uvnitř takové databáze, můžete vyzkoušet program IBSurgeonViewer (freeware pro Windows) a prohlédnout si obsah systémových tabulek (jejich jméno začíná na RDB$).

Pokud jste při provádění výše popsaného neudělali žádnou chybu, budou smazaná data přístupná a můžete je pomocí vhodného nástroje vyexportovat (např. do SQL skriptu). Pak již stačí jen opětovně vytvořit původní tabulku, naplnit ji vyexportovanými daty, databázi zazálohovat a opět ji obnovit, a vaše databáze je opět jako nová. Tedy v tom lepším případě. Naštěstí tentokrát transplantace skutečně zafungovala (i tak mi to u 400MB databáze zabralo dva dny), a vyzobávání a dekódování dat řádek po řádku nebylo nutné, což jsem moc rád, protože i když víte co a jak, byla by to zábava přinejlepším na týden.

Velikonoce jsem tedy nestrávil v práci, ale jak se sluší a patří, a tento týden se snad konečně vrhnu na psaní testů (ťuky ťuky na dřevo).

Sdílet