Chci probrat appkuMáte SW problém?
Zpět na blog
TechnologieDatabázeMigraceZe zákulisíBackend

Databáze plná překvapení: Příběhy z migrací

Lukáš Huso19. března 20266 min čtení
Databáze plná překvapení: Příběhy z migrací
Photo: Jan Antonin Kolar / Unsplash

Databáze je srdce každé aplikace. A jako u skutečného srdce — když začne vynechávat, je to problém. Za roky praxe jsme migrovali, opravovali a zachraňovali databáze, které by neměly existovat. A přesto existovaly, v produkci, s reálnými daty reálných lidí.

Toto jsou příběhy, po kterých jsme potřebovali kávu. Někdy i něco silnějšího.

Tabulka s pěti sty sloupci

Normalizace je jeden ze základních principů databázového designu. Existují učebnice, kurzy, certifikace. A přesto jsme narazili na tabulku, která měla přesně 487 sloupců. Jednu tabulku. Pro všechno.

Jmenovala se data. Ne users, ne orders, ne products. Prostě data. A obsahovala sloupce jako: name, name2, name3, address_home, address_work, address_other, address_other2, phone1phone5, note1note20, a náš favorit: temp_column_do_not_use_7.

Dočasný sloupec, který se neměl používat. Sedmý v řadě. Což znamená, že bylo minimálně šest předchozích dočasných sloupců, které se také neměly používat.

Celá aplikace stavěla na jedné obrovské tabulce místo relačního modelu. Přidání nového typu informace znamenalo přidání dalšího sloupce. Hledání dat bylo jako hledání jehly v kupce sena — pokud by ta kupka měla 487 jehel a vy nevěděli, která je ta správná.

Datumy v dvanácti formátech

Datum je datum, říkáte si. Jednoduché. A přesto jsme v jedné databázi našli sloupec datum_objednavky (typ VARCHAR, samozřejmě) s těmito hodnotami:

  • 2023-01-15
  • 15.1.2023
  • 15/01/2023
  • Jan 15, 2023
  • 15. ledna 2023
  • 1/15/23
  • 20230115
  • pondělí 15. ledna
  • minulý týden
  • brzy
  • ?
  • prázdný řetězec

Dvanáct různých formátů (pokud počítáme "brzy" a "?" jako formáty, což s jistou kreativitou můžeme). Důvod? Pole v aplikaci bylo prostý textový input bez jakékoliv validace. Uživatelé prostě psali datum, jak je napadlo. A systém to s radostí uložil.

Migrace do správného datumového typu trvala dva týdny. Dva týdny parsování, hádání a občasného volání klientovi s otázkou: "Víte, co znamená objednávka s datem 'brzy' z roku 2021?"

Pole pro adresu jako univerzální zápisník

V jedné starší aplikaci existovalo pole adresa, které mělo sloužit — překvapivě — k ukládání adres. V praxi obsahovalo:

  • Skutečné adresy (asi 60 % záznamů)
  • Telefonní čísla ("602123456 — volat odpoledne")
  • E-mailové adresy
  • Poznámky k objednávkám ("Nechte u sousedů, zazvoňte 3x")
  • Nákupní seznamy (doslova: "máslo, chleba, salám")
  • Existenciální úvahy jednoho operátora ("Proč tady vlastně pracuju?")

Když jsme se klienta zeptali, jak se to stalo, odpověděl: "Operátoři si stěžovali, že nemají kam psát poznámky. Tak jsme jim řekli, ať používají pole adresa, že to pak vyřešíme." To bylo v roce 2018. Nikdo to nevyřešil.

Sloupec isDeleted a kvantová fyzika

Soft delete — označení záznamu jako smazaného místo skutečného smazání — je rozumný přístup. Ale vyžaduje konzistenci. V jednom projektu jsme našli sloupec isDeleted, který obsahoval tyto hodnoty:

  • 0 (zřejmě ne)
  • 1 (zřejmě ano)
  • true (textový řetězec)
  • false (textový řetězec)
  • yes
  • no
  • Y
  • N
  • maybe (opravdu)
  • NULL
  • deleted
  • not_deleted
  • prázdný řetězec

Sloupec isDeleted se tak stal kvantovým objektem — záznam byl současně smazaný i nesmazaný, dokud ho někdo nepozoroval. A ani pak to nebylo jisté.

Zjistili jsme, že na projektu pracovalo postupně sedm různých vývojářů. Každý měl svou představu o tom, co do sloupce patří. A nikdo se neobtěžoval podívat, co tam dávali ostatní.

Padesát gigabajtů obrázků v databázi

Existuje věčná debata o tom, jestli ukládat obrázky do databáze, nebo na souborový systém. Většina rozumných vývojářů ukládá obrázky na disk (nebo do cloudového úložiště) a do databáze dává jen cestu. Ale ne všichni vývojáři jsou rozumní.

Převzali jsme e-shop, jehož databáze měla 53 GB. Pro e-shop s pár tisíci produkty to bylo podezřelé. Po průzkumu jsme zjistili, že každý produkt měl obrázky uložené jako BLOB přímo v databázi. Ale to nebylo to nejhorší.

Každý obrázek byl uložen v originálním rozlišení z fotoaparátu — 24 megapixelů, asi 8 MB na fotku. Nikdo je nezmenšoval. A ke každému produktu bylo 5-10 fotek. A celá historie — když prodejce nahrál novou fotku, stará se nesmazala, jen se přidal nový záznam.

Záloha databáze trvala čtyři hodiny. Obnovení šest. A MySQL server občas padal, protože padesát tři gigabajtů dat není úplně to, na co je optimalizovaný.

Produkce bez záloh

A teď ten skutečně děsivý příběh. Zavolal nám klient v panice. Jejich webová aplikace nefunguje. Server spadl. Zeptali jsme se na zálohy. Odpověď:

"Zálohy? To dělá hosting automaticky, ne?"

Ne. Nedělá. Respektive — v tomto případě ne. Hosting měl zálohy v ceníku jako placenou službu. Klient si ji neobjednal. A nikdo jiný zálohy neřešil.

Disk serveru měl hardwarovou chybu. Část dat byla poškozená. Databáze se nedala obnovit. Pět let zákaznických dat, objednávek, faktur — pryč.

Tuhle situaci jsme bohužel nezvládli vyřešit mávnutím kouzelného proutku. Podařilo se zachránit asi 70 % dat z poškozeného disku specializovanou firmou. Za cenu, která mnohonásobně převyšovala roční náklady na zálohovací službu.

Proč se to děje

Špatný databázový design obvykle nevzniká najednou. Je to postupný proces. Někdo vytvoří "dočasné" řešení, které se stane permanentním. Někdo přidá sloupec místo nové tabulky, protože je to rychlejší. Někdo vypne validaci, protože "teď nemáme čas to řešit."

A každá tahle zkratka je v pořádku, pokud se k ní vrátíte a opravíte ji. Problém je, že se k ní nikdo nevrátí. A za dva roky máte databázi, kde sloupec "adresa" obsahuje nákupní seznamy.

Špatně
  • Žádné indexy na tabulkách s miliony řádků
  • Jedna obří tabulka pro všechna data
  • Žádné zálohy nebo netestované zálohy
  • Žádná validace — databáze jako hloupé úložiště
  • Ruční úpravy schématu v produkci
  • Obrázky a soubory uložené jako BLOB v DB
Správně
  • Indexování klíčových sloupců
  • Normalizace datového modelu
  • Automatické zálohy s testováním obnovy
  • Validace na úrovni databáze (NOT NULL, CHECK)
  • Migrace verzované v kódu
  • Binární data na souborovém systému

Jak tomu předejít

Pár základních pravidel, která ušetří hodiny bolesti:

Navrhněte datový model předem. Před prvním řádkem kódu. Nakreslete schéma, definujte vztahy, zvolte správné datové typy.

Používejte migrace. Verzované, opakovatelné, reverzibilní. Žádné ruční úpravy databáze v produkci.

Validujte na úrovni databáze. NOT NULL, UNIQUE, CHECK constrainty, cizí klíče. Nedělejte z databáze hloupé úložiště.

Zálohujte. Automaticky, pravidelně, a ověřujte, že se zálohy dají obnovit. Záloha, kterou jste nikdy netestovali, není záloha.

Neukládejte binární data do databáze. Obrázky, PDF, videa patří na souborový systém nebo do objektového úložiště.

Zálohujte databázi minimálně jednou denně a zálohy pravidelně testujte obnovou na testovacím prostředí. Při migraci vždy nejdřív zálohujte, pak migrujte na staging a teprve po ověření na produkci. Jedna netestovaná záloha je horší než žádná — dává vám falešný pocit bezpečí.

Poučení na závěr

Databáze je základ, na kterém stojí celá aplikace. Když jsou základy špatné, dříve nebo později se to projeví — a oprava stojí řádově víc, než by stálo udělat to správně od začátku.

Morál příběhu: Datová architektura není něco, co se dá odložit na "potom." Investujte do ní od prvního dne. Váš budoucí já — nebo vývojář, který po vás projekt zdědí — vám poděkuje. A nebudete muset nikomu vysvětlovat, proč sloupec isDeleted obsahuje hodnotu "maybe."

Spočítejte si cenu na míru

Konfigurátor vám za 2 minuty ukáže orientační cenu přesně pro váš projekt.

Související články

Bezpečnostní díry, které jsme opravovali po ostatních
TechnologieBezpečnostZe zákulisí

Bezpečnostní díry, které jsme opravovali po ostatních

Komentovaný auth kód, hesla v API odpovědích, JWT secret 'secret123'. Reálné bezpečnostní noční můry z převzatých projektů.

23. dubna 20266 min čtení
Serverless architektura: Kdy se vyplatí a kdy ne
TechnologieServerlessCloud

Serverless architektura: Kdy se vyplatí a kdy ne

Praktický rozbor serverless architektury. Kdy ušetříte, kdy ne, jaká jsou rizika vendor lock-inu a pro jaké projekty se serverless skutečně hodí.

21. dubna 20268 min čtení
API-first přístup: Proč začít backendem
TechnologieAPIBackend

API-first přístup: Proč začít backendem

Co znamená API-first vývoj, jaké jsou jeho výhody a jak může ušetřit čas i peníze. REST vs GraphQL, dokumentace a praktické zkušenosti.

17. března 20268 min čtení