30.8.2015
Můj firemní kolega Tomáš Hofman nedávno psal o obnově tabulek v databázi MySql: Obnova InnoDB tabulek v MySQL. Pokud budete potřebovat vědět cokoliv o databázi MySql, zeptejte se raději jeho. Já neumím v databázi MySql nastavit ani uživatele. Tradičně tuto databázi obcházím širokým obloukem, zákazníkům ji nedoporučuji, nepoužívám ji a projekty, které tuto databázi používají, ve mě nebudí velkou důvěru.
I přes svůj odpor k této databázi se občas dostanu do kontaktu s aplikací, která v MySql ukládá svá data. Před pár lety jsem se dostal k primitivní aplikaci pro sběr dat z fotovoltaických elektráren. Aplikace měla několik částí: jednoduchý PHP skript pro výběr dat z databáze, server Apache, program fslurp pro komunikaci se střídači Fronius, perlovský skript na parsování výstupů z programu fslurp a cron, který to vše periodicky spuštěl. Celé to bylo velmi primitivní, nepřehledné, kritické na načasování a složité na nastavování - všechny konfigurační parametry byly zadrátované přímo ve zdrojových skriptech, na každé elektrárně tak muselo být něco jiného. Tvůrce tohoto skvostu pak sáhl automaticky po databázi MySql - chápejte to jako vysvětlení mé nedůvěry k čemukoliv, co do MySql ukládá data. Když sahám po aplikaci s MySql, vždy ve mě dříme strach z něčeho takového.
V databázi samotné pak nebylo nic složitého: šlo o dvě tabulky - v jedné byly uložené naměřené hodnoty zhruba týden dozadu a v druhé tabulce byl uložený aktuální stav každého střídače (autor nedokázal vytáhnout poslední stav z archivní tabulky). Tabulky byly uložené ve formátu MyISAM. Netuším, jestli tento formát dovede zajistit referenční integritu, v této databázi rozhodně nic takového nebylo. V archivní tabulce bylo běžně několik desítek tisíc záznamů, v tabulce s aktuálním stavem pak bylo do stovky záznamů. Databáze tedy byla maličká a velmi jednoduchá.
Přesto, že největší hrůzy byly k vidění v samotné aplikaci, nejvíce problémů kupodivu dělala databáze MySql, a to i přes jednoduchost a prťavost databázových tabulek. Aplikace byla nainstalovaná na dvaceti elektrárnách. PC sice bylo bez UPS, ale uptime je zde běžně čtvrt roku a více. Typicky se projevovaly dvě závady:
Frekvence zhruba dvakrát až třikrát za měsíc. Pomoc byla snadná, stačilo nastartovat v databázi příkaz "repair table". Pokaždé to však znamenalo ztrátu dat po dobu havárie a vyžadovalo to ruční zásah. Většinou závada souvisela s výpadky napájecího napětí, ale docela často byly tabulky poškozené i bez výpadku.
Druhá, mnohem zákeřnější závada spočívala v neprovedém update v tabulce. V tabulce s aktuálním stavem se každý záznam co pár minut přepisoval novým stavem. Pokud se projevila tato závada, některé záznamy se jednoduše nepřepsaly. Z běžně připojených sedmdesáti střídačů se třeba u pěti nepodařilo databázi aktualizovat příslušný záznam. Příkaz update přitom zcela normálně proběhnul bez chybových hlášení. Aplikace neměla nejmenší šanci chybu poznat - jedinou možností bylo přečíst po každém zápisu skutečný stav z databáze a porovnat s tím, co se skutečně mělo zapsat. Aplikace nic takového pochopitelně nedělala.
Jakmile se tato závada projevila, nedalo se dělat nic jiného, než celou databázovou tabulku smazat a vytvořit znovu. Nepodařilo se mi vypozorovat jakoukoliv souvislost s výpadky napájení.
Zákeřnost a nepřijatelnost takového chování spočívá především v tom, že na data v databázi se nelze spolehnout. S databází MySql na elektrárnách jsem si nikdy nebyl jistý, jestli data přečtená z databáze odpovídají skutečnosti, nebo jsem dostal něco, co si před chvílí databáze MySql vymyslela.
Zmíněné problémy se nám nikdy nepodařilo odstranit. Navíc aplikace byla tak příšerně napsaná, že nejlepším východiskem se nakonec ukázalo začít na zelené louce a celou aplikaci vytvořit znovu.
Výsledkem je program Fotobot. Aplikace je volně dostupná pod licencí GPL (používá se zde několik knihoven s touto licencí).
Aplikace Fotobot přistupuje ke stejnému problému zcela jinak:
Databáze SQLite se jeví pro podobné použití jako podstatně vhodnější, než MySql. Databáze je vestavěná přímo v aplikaci, není potřebný žádný databázový server. Databáze je sice jednovláknová - není možné, aby k databázi přistupovalo několik uživatelů najednou, ale v embedded aplikacích, jakou je Fotobot, to nevadí. Dotazy většinou trvají jen velmi krátkou dobu a single přístup do databáze lze v aplikaci zajistit jednoduchým zamykáním. Z hlediska spolehlivosti se databáze SQLite s MySql vůbec nedá srovnávat, SQLite je jednoduchá a tak dobře otestovaná, že výše popsané události s databází SQLite prakticky vůbec nepřipadají v úvahu. Během našeho používání SQLite jsme nikdy nenarazili na žádnou chybu způsobenou databází.
SQLite je nejpoužívanější databází na světě. SQLite se používá více, než všechny ostatní databáze dohromady: Most Widely Deployed and Used Database Engine.
Databáze SQLite ukládá data v jediném souboru. Do určité velikosti souboru je databáze dostatečně rychlá, při velikostech kolem 1GB však může start aplikace trvat nepříjmeně dlouho. Po výpadcích napájení databázový engine kontroluje konzistenci databáze, aplikace je v tu dobu zablokovaná. Proto je vhodné ukládat do databáze spíše menší objemy dat. V databázi ukládáme běžně stovky tisíc záznamů, vyjímečně něco málo přes milión. Velikost databáze málokdy přesáhne 100 MB. Databázový soubor je díky tomu možné umístit i na ramdisk, rychlost databáze díky tomu může být přímo blesková i v počítači typu Beaglebone. Databáze samozřejmě zvládne i mnohem větší objemy dat, ale základním předpokladem je v takovém případě kvalitní UPS a stabilní aplikace bez havárií.
Dodatečná poznámka: zajímalo mě, co se vlastně s databází při startu aplikace děje, takže jsem se začetl do materiálů o SQLite. Výsledek? Nevím. Při startu aplikace vídávám na disku jednak samotnou databázi a také soubor s příponou "-journal". Mohl se mi do startu aplikace zatoulat příkaz VACUUM? Nebo jsem někde zapomenul uzavřít transakci příkazem COMMIT? Každopádně je to už jedno, maximální velikost databáze dnes u nás nepřesahuje stovky MB a rychlost je pekelná.
Kdy zvolit databázi SQLite: Appropriate Uses For SQLite.