Rezervační systém
Otázka nepersitentní povahy databáze

Obsah

Popis řešení

Databáze realizovaná pomocí třídy CMemoryDb má jistě výhodu ve velkém výkonu, což je dáno tím, že data jsou uložena přímo v operční paměti (pokud díky zatížení stroje jinými procesy nemusí být odkládána do stránkovacího souboru operačního systému). Je zřejmé, že největším problémem tohoto přístupu je problém neperzistence takto uložených dat, tj. skutečnost, že při náhlém výpadku hardware jsou data od poslední zálohy ztracena.

Aby se předešlo tomuto hrozivému scénáři, jsou operace měnící data uložená v databázi ukládána do souboru na disku (do žurnálu). Pořadí operací odpovídá tomu, jak přicházejí jednotlivé klientské požadavky. Pokud soubor žurnálu dosáhne přednastaveného limitu, je provedena záloha celé databáze a žurnál je vymazán. Taková interní záloha je vždy provedena i při legálním ukončení aplikace. Při opětovném spuštění jsou data z této zálohy načtena a server může normálně pokračovat v činnosti.

Za normálních okolností je v okamžiku spuštění serverové aplikace soubor žurnálu prázdný. Pokud však byla aplikace ukončena nelegálně, obsahuje žurnál vlastně operace provedené od poslední zálohy. V tomto případě pak stačí "přehrát" operace ze žurnálu, čímž se databáze uvede do platného stavu, ve kterém byla těsně před ukončením serverové aplikace.

Implementace

Soubor se žurnálem i interní záloha celé databáze jsou vytvářeny v adresáři, který je určen konfiguračním souborem. Je nutno zajistit existenci tohoto adresáře i správné oprávnění k přístupu pro serverovou aplikaci.

Vytváření žurnálu

Práci s vytvářením žurnálového souboru zapoudřuje třída CWriteJournal. Její instance je vytvořena pomocí instance databáze CMemoryDb po dobu aktivní činnosti serverové aplikace (tj. je vytvářena následkem příkazu START a rušena po příkazu STOP).

Třída spravuje žurnálový soubor a poskytuje metodu pro přidávání jednotlivých záznamů (tj. příkazů, které vedou ke změně údajů v databázi). Zároveň si vytváří pracovní vlákno, které při překročení přednastavené velikosti žurnálu provede kompletní zálohu databáze a žurnál vyprázdní. K tomu potřabuje získat výhradní přístup k databázi a musí tedy počkat na dokončení všech dalších souběžně probíhajících operací (viz). Díky zmíněnému systému zámků a vnitřní synchronizaci v CWriteJournal je zajištěno, že záznamy v žurnálu jsou uvedeny ve správném pořadí dle vyřizování požadavků (a tedy správně odrážejí přidělování čísel autobusů apod. jakož i následnost dalších operací).

Při provádění interní zálohy databáze je stávající soubor dočasně přejmenován a po úspěšném provedení oprace vymazán. Data tedy nejsou ztracena ani v případě pádu aplikace (např. vlivem selhání hardware) během provádění zálohy. Až poté je vyprázdněn vlastní žurnálovací soubor.

Požadavek na provedení interní zálohy lze vyvolat i z vnějšku - to je prováděno např. při legálním ukončování serverové aplikace. Tímto způsobem je zajištěno, že při normálním ukončení aplikace je soubor žurnálu prázdný a interní záloha databáze odráží poslední platný stav dat.

Zpracování žurnálu

Serverová aplikace při startu hledá soubor s interní zálohou databáze, která byla provedena při posledním ukončení. Z tohoto souboru dojde k obnovení databáze. Pokud aplikace nebyla ukončena legálně, může existovat žurnálový soubor s neprázdným obsahem.

Zpracování žurnálu má na starosti třída CReadJournal. Její nejdůležitější součást je metoda CReadJournal::Replay, která zabezpečuje postupné vyzvedávání položek ze souboru a následně vykonává jednotlivá volání databázového rozhraní se stejnými parametry, které byly dříve uloženy. Tímto způsobem se databáze dostane do konzistentního stavu, která odpovídá stavz těsně před havárií aplikace.