O databázach by to malo vedieť viac vývojárov

Poznámka. preklad.: Jaana Dogan je skúsená inžinierka v Google, ktorá momentálne pracuje na pozorovateľnosti produkčných služieb spoločnosti napísaných v Go. V tomto článku, ktorý si získal veľkú obľubu medzi anglicky hovoriacim publikom, zozbierala v 17 bodoch dôležité technické detaily týkajúce sa DBMS (a niekedy aj distribuovaných systémov vo všeobecnosti), ktoré je užitočné zvážiť pre vývojárov veľkých/náročných aplikácií.

O databázach by to malo vedieť viac vývojárov

Prevažná väčšina počítačových systémov sleduje svoj stav, a preto si vyžaduje nejaký druh systému ukladania údajov. Znalosti o databázach som nazbieral počas dlhého obdobia, pričom som robil chyby v dizajne, ktoré viedli k strate údajov a výpadkom. V systémoch, ktoré spracúvajú veľké objemy informácií, sú databázy jadrom architektúry systému a fungujú ako kľúčový prvok pri výbere optimálneho riešenia. Napriek tomu, že sa práci databázy venuje veľká pozornosť, problémy, ktoré sa vývojári aplikácií snažia predvídať, sú často len špičkou ľadovca. V tejto sérii článkov zdieľam niekoľko nápadov, ktoré budú užitočné pre vývojárov, ktorí sa v tejto oblasti nešpecializujú.

  1. Máte šťastie, ak sieť v 99,999 % prípadov nespôsobuje problémy.
  2. ACID znamená veľa rôznych vecí.
  3. Každá databáza má svoje vlastné mechanizmy na zabezpečenie konzistencie a izolácie.
  4. Optimistické blokovanie prichádza na záchranu, keď je ťažké udržať obvyklé.
  5. Okrem nečistého čítania a straty údajov existujú aj iné anomálie.
  6. Nie vždy sa databáza a používateľ zhodnú na postupe.
  7. Sharding na úrovni aplikácie je možné presunúť mimo aplikácie.
  8. Autoinkrementácia môže byť nebezpečná.
  9. Zastarané údaje môžu byť užitočné a nemusia byť uzamknuté.
  10. Skreslenia sú typické pre akékoľvek časové zdroje.
  11. Oneskorenie má veľa významov.
  12. Požiadavky na výkon by sa mali vyhodnotiť pre konkrétnu transakciu.
  13. Vnorené transakcie môžu byť nebezpečné.
  14. Transakcie by nemali byť viazané na stav aplikácie.
  15. Plánovač dopytov vám môže povedať veľa o databázach.
  16. Online migrácia je náročná, ale možná.
  17. Výrazný nárast v databáze znamená zvýšenie nepredvídateľnosti.

Chcel by som poďakovať Emmanuelovi Odekeovi, Reinovi Henrichsovi a ďalším za ich spätnú väzbu na staršiu verziu tohto článku.

Máte šťastie, ak sieť v 99,999 % prípadov nespôsobuje problémy.

Otázkou zostáva, nakoľko spoľahlivé sú moderné sieťové technológie a ako často sú systémy mimo prevádzky v dôsledku zlyhania siete. Informácií o tejto problematike je málo a výskumu často dominujú veľké organizácie so špecializovanými sieťami, vybavením a personálom.

S mierou dostupnosti 99,999 % pre Spanner (globálne distribuovaná databáza Google) Google tvrdí, že iba 7,6% problémy súvisia so sieťou. Spoločnosť zároveň svoju špecializovanú sieť nazýva „hlavným pilierom“ vysokej dostupnosti. Štúdium Bailis a Kingsbury, uskutočnený v roku 2014, spochybňuje jednu z „mylné predstavy o distribuovaných výpočtoch“, ktorý Peter Deutsch sformuloval v roku 1994. Je sieť skutočne spoľahlivá?

Komplexný výskum mimo gigantických spoločností, vykonávaný pre širší internet, jednoducho neexistuje. Od hlavných hráčov tiež nie je dostatok údajov o tom, aké percento problémov ich zákazníkov súvisí so sieťou. Sme si dobre vedomí výpadkov v sieti veľkých poskytovateľov cloudu, ktoré môžu na niekoľko hodín odobrať celý kus internetu len preto, že ide o významné udalosti, ktoré ovplyvňujú veľké množstvo ľudí a spoločností. Výpadky siete môžu spôsobiť problémy v mnohých ďalších prípadoch, aj keď nie všetky tieto prípady sú v centre pozornosti. Klienti cloudových služieb tiež nevedia nič o príčinách problémov. Ak dôjde k poruche, je takmer nemožné pripísať ju chybe siete na strane poskytovateľa služieb. Služby tretích strán sú pre nich čiernymi skrinkami. Nie je možné posúdiť vplyv bez toho, aby ste boli veľkým poskytovateľom služieb.

Vzhľadom na to, čo o svojich systémoch hlásia veľkí hráči, možno s istotou povedať, že máte šťastie, ak problémy so sieťou predstavujú len malé percento potenciálnych problémov s výpadkami. Sieťová komunikácia stále trpí takými všednými vecami, ako sú zlyhania hardvéru, zmeny topológie, zmeny administratívnej konfigurácie a výpadky napájania. Nedávno som bol prekvapený, keď som sa dozvedel, že bol pridaný zoznam možných problémov uhryznutie žralokom (áno, počuli ste dobre).

ACID znamená veľa rôznych vecí

Skratka ACID znamená Atomicita, Konzistencia, Izolácia, Spoľahlivosť. Tieto vlastnosti transakcií majú zabezpečiť ich platnosť v prípade porúch, chýb, porúch hardvéru atď. Bez ACID alebo podobných schém by bolo pre vývojárov aplikácií ťažké rozlíšiť, za čo sú zodpovední oni a za čo je zodpovedná databáza. Väčšina relačných transakčných databáz sa snaží byť v súlade s ACID, ale nové prístupy ako NoSQL viedli k vzniku mnohých databáz bez transakcií ACID, pretože ich implementácia je nákladná.

Keď som prvýkrát vstúpil do odvetvia, náš technický vedúci hovoril o tom, aký dôležitý je koncept ACID. Aby sme boli spravodliví, ACID sa považuje skôr za hrubý popis ako za prísny implementačný štandard. Dnes to považujem za užitočné, pretože nastoľuje špecifickú kategóriu problémov (a navrhuje celý rad možných riešení).

Nie každý DBMS je kompatibilný s ACID; Implementácie databáz, ktoré podporujú ACID, zároveň chápu súbor požiadaviek odlišne. Jedným z dôvodov, prečo sú implementácie ACID nejednotné, je množstvo kompromisov, ktoré je potrebné urobiť pri implementácii požiadaviek ACID. Tvorcovia môžu prezentovať svoje databázy ako ACID-kompatibilné, ale interpretácia hraničných prípadov sa môže dramaticky líšiť, rovnako ako mechanizmus spracovania „nepravdepodobných“ udalostí. Vývojári môžu prinajmenšom získať pochopenie zložitosti základných implementácií na vysokej úrovni, aby správne pochopili ich špeciálne správanie a kompromisy v dizajne.

Debata o tom, či MongoDB spĺňa požiadavky ACID pokračuje aj po vydaní verzie 4. MongoDB už dlho nie je podporovaný ťažba dreva, hoci v predvolenom nastavení sa údaje odosielali na disk maximálne raz za 60 sekúnd. Predstavte si nasledujúci scenár: aplikácia odošle dva zápisy (w1 a w2). MongoDB úspešne ukladá w1, ale w2 sa stratí v dôsledku zlyhania hardvéru.

O databázach by to malo vedieť viac vývojárov
Diagram znázorňujúci scenár. MongoDB zlyhá skôr, ako môže zapisovať údaje na disk

Zaviazanie na disk je nákladný proces. Tým, že sa vývojári vyhnú častým potvrdeniam, zlepšujú výkon nahrávania na úkor spoľahlivosti. MongoDB v súčasnosti podporuje protokolovanie, ale nečisté zápisy môžu stále ovplyvniť integritu údajov, pretože protokoly sa štandardne zaznamenávajú každých 100 ms. To znamená, že podobný scenár je stále možný pre protokoly a zmeny v nich uvedené, hoci riziko je oveľa nižšie.

Každá databáza má svoje vlastné mechanizmy konzistencie a izolácie

Z požiadaviek ACID sa konzistentnosť a izolácia môžu pochváliť najväčším počtom rôznych implementácií, pretože rozsah kompromisov je širší. Treba povedať, že konzistencia a izolácia sú dosť drahé funkcie. Vyžadujú koordináciu a zvyšujú konkurenciu pre konzistentnosť údajov. Zložitosť problému sa výrazne zvyšuje, keď je potrebné škálovať databázu horizontálne naprieč viacerými dátovými centrami (najmä ak sa nachádzajú v rôznych geografických oblastiach). Dosiahnutie vysokej úrovne konzistencie je veľmi ťažké, pretože to tiež znižuje dostupnosť a zvyšuje segmentáciu siete. Pre všeobecnejšie vysvetlenie tohto javu vám odporúčam odkázať na CAP veta. Za zmienku tiež stojí, že aplikácie dokážu zvládnuť malé množstvá nekonzistentnosti a programátori dokážu dostatočne dobre porozumieť nuansám problému na to, aby do aplikácie implementovali dodatočnú logiku na zvládnutie nekonzistentnosti bez toho, aby sa vo veľkej miere spoliehali na databázu.

DBMS často poskytujú rôzne úrovne izolácie. Vývojári aplikácií si môžu vybrať tú najefektívnejšiu na základe svojich preferencií. Nízka izolácia umožňuje vyššiu rýchlosť, ale tiež zvyšuje riziko dátových pretekov. Vysoká izolácia znižuje túto pravdepodobnosť, ale spomaľuje prácu a môže viesť ku konkurencii, čo povedie k takým brzdám v základni, že začnú poruchy.

O databázach by to malo vedieť viac vývojárov
Preskúmanie existujúcich modelov súbežnosti a vzťahov medzi nimi

Štandard SQL definuje iba štyri úrovne izolácie, hoci teoreticky a prakticky ich je oveľa viac. Jepson.io ponúka vynikajúci prehľad existujúcich modelov súbežnosti. Napríklad Google Spanner zaručuje externú serializáciu so synchronizáciou hodín, a hoci ide o prísnejšiu izolačnú vrstvu, nie je definovaná v štandardných izolačných vrstvách.

Štandard SQL uvádza nasledujúce úrovne izolácie:

  • Serializable (najprísnejšie a najdrahšie): Serializovateľné vykonávanie má rovnaký účinok ako vykonávanie niektorých sekvenčných transakcií. Sekvenčné vykonávanie znamená, že každá nasledujúca transakcia začína až po dokončení predchádzajúcej. Treba poznamenať, že úroveň Serializable často implementovaná ako takzvaná izolácia snímok (napríklad v Oracle) kvôli rozdielom v interpretácii, hoci samotná izolácia snímok nie je zastúpená v štandarde SQL.
  • Opakovateľné čítania: Nepotvrdené záznamy v aktuálnej transakcii sú dostupné pre aktuálnu transakciu, ale zmeny vykonané inými transakciami (napríklad nové riadky) neviditeľný.
  • Čítajte odhodlane: Nepotvrdené údaje nie sú k dispozícii pre transakcie. V tomto prípade môžu transakcie vidieť iba potvrdené údaje a môžu sa vyskytnúť fantómové čítania. Ak transakcia vloží a potvrdí nové riadky, aktuálna transakcia ich bude môcť vidieť pri dotaze.
  • Čítajte nezáväzne (najmenej prísna a drahá úroveň): Nečisté čítania sú povolené, transakcie môžu vidieť nepotvrdené zmeny vykonané inými transakciami. V praxi môže byť táto úroveň užitočná pre hrubé odhady, ako sú napríklad dotazy COUNT(*) na stole.

Úroveň Serializable minimalizuje riziko dátových pretekov, pričom je najdrahšia na implementáciu a výsledkom je najvyššie konkurenčné zaťaženie systému. Iné úrovne izolácie sú jednoduchšie na implementáciu, ale zvyšujú pravdepodobnosť dátových pretekov. Niektoré DBMS vám umožňujú nastaviť vlastnú úroveň izolácie, iné majú silné preferencie a nie všetky úrovne sú podporované.

Podpora úrovní izolácie je v danom DBMS často inzerovaná, ale iba starostlivé štúdium jeho správania môže odhaliť, čo sa v skutočnosti deje.

O databázach by to malo vedieť viac vývojárov
Preskúmanie anomálií súbežnosti na rôznych úrovniach izolácie pre rôzne DBMS

Martin Kleppmann vo svojom projekte pustovňa Porovnáva rôzne úrovne izolácie, hovorí o anomáliách súbežnosti a o tom, či je databáza schopná dodržiavať určitú úroveň izolácie. Kleppmannov výskum ukazuje, ako rozdielne rozmýšľajú vývojári databáz o úrovniach izolácie.

Optimistické blokovanie prichádza na záchranu, keď je ťažké udržať obvyklé.

Blokovanie môže byť veľmi drahé, nielen preto, že zvyšuje konkurenciu v databáze, ale aj preto, že vyžaduje, aby sa aplikačné servery neustále pripájali k databáze. Segmentácia siete môže zhoršiť exkluzívne uzamykacie situácie a viesť k zablokovaniu, ktoré je ťažké identifikovať a vyriešiť. V prípadoch, keď exkluzívne zamykanie nie je vhodné, pomáha optimistické zamykanie.

Optimistický zámok je metóda, pri ktorej sa pri čítaní reťazca berie do úvahy jeho verzia, kontrolný súčet, prípadne čas poslednej úpravy. To vám umožňuje zabezpečiť, aby nedošlo k žiadnej zmene atómovej verzie pred zmenou položky:

UPDATE products
SET name = 'Telegraph receiver', version = 2
WHERE id = 1 AND version = 1

V tomto prípade aktualizujte tabuľku products sa nevykoná, ak iná operácia predtým vykonala zmeny v tomto riadku. Ak na tomto riadku neboli vykonané žiadne ďalšie operácie, dôjde k zmene pre jeden riadok a môžeme povedať, že aktualizácia bola úspešná.

Okrem nečistého čítania a straty údajov existujú aj iné anomálie

Pokiaľ ide o konzistenciu údajov, dôraz sa kladie na potenciál pre závodné podmienky, ktoré môžu viesť k nečistým čítaniam a strate údajov. Dátové anomálie tam však nekončia.

Jedným z príkladov takýchto anomálií je skreslenie záznamu (píšte šikmo). Skreslenie je ťažké odhaliť, pretože sa zvyčajne aktívne nevyhľadáva. Nie sú spôsobené nečistými čítaniami alebo stratou údajov, ale porušením logických obmedzení kladených na údaje.

Zoberme si napríklad monitorovaciu aplikáciu, ktorá vyžaduje, aby bol jeden operátor neustále v pohotovosti:

BEGIN tx1;                      BEGIN tx2;
SELECT COUNT(*)
FROM operators
WHERE oncall = true;
0                               SELECT COUNT(*)
                                FROM operators
                                WHERE oncall = TRUE;
                                0
UPDATE operators                UPDATE operators
SET oncall = TRUE               SET oncall = TRUE
WHERE userId = 4;               WHERE userId = 2;
COMMIT tx1;                     COMMIT tx2;

Vo vyššie uvedenej situácii dôjde k poškodeniu záznamu, ak sú obe transakcie úspešne vykonané. Hoci nedošlo k žiadnym nečistým čítaniam alebo strate údajov, integrita údajov bola narušená: teraz sú dvaja ľudia v rovnakom čase.

Serializovateľná izolácia, návrh schémy alebo obmedzenia databázy môžu pomôcť eliminovať poškodenie zápisu. Vývojári musia byť schopní identifikovať takéto anomálie počas vývoja, aby sa im vo výrobe vyhli. Zároveň sa skreslenia záznamu v kódovej základni hľadajú mimoriadne ťažko. Najmä vo veľkých systémoch, keď sú rôzne vývojové tímy zodpovedné za implementáciu funkcií založených na rovnakých tabuľkách a nezhodujú sa v špecifikách prístupu k dátam.

Databáza a používateľ sa nie vždy zhodnú na tom, čo robiť

Jednou z kľúčových vlastností databáz je garancia príkazu na vykonanie, ale tento príkaz sám o sebe nemusí byť pre vývojára softvéru transparentný. Databázy vykonávajú transakcie v poradí, v akom boli prijaté, nie v poradí, v akom zamýšľajú programátori. Poradie transakcií je ťažké predpovedať, najmä vo vysoko zaťažených paralelných systémoch.

Počas vývoja, najmä pri práci s neblokovacími knižnicami, môže zlý štýl a nízka čitateľnosť spôsobiť, že používatelia budú veriť, že transakcie sa vykonávajú postupne, pričom v skutočnosti môžu do databázy doraziť v akomkoľvek poradí.

Na prvý pohľad sa v nižšie uvedenom programe volajú T1 a T2 postupne, ale ak sú tieto funkcie neblokujúce a okamžite vrátia výsledok vo forme sľub, potom bude poradie hovorov určené okamihmi, kedy vstúpili do databázy:

výsledok1 = T1() // skutočné výsledky sú sľuby
výsledok2 = T2()

Ak sa vyžaduje atomicita (to znamená, že všetky operácie musia byť dokončené alebo prerušené) a záleží na sekvencii, operácie T1 a T2 sa musia vykonať v rámci jednej transakcie.

Sharding na úrovni aplikácie je možné presunúť mimo aplikácie

Zdieľanie je metóda horizontálneho rozdelenia databázy. Niektoré databázy dokážu automaticky horizontálne rozdeliť dáta, zatiaľ čo iné nie, alebo nie sú v tom príliš dobré. Keď sú dátoví architekti/vývojári schopní presne predpovedať, ako sa k dátam bude pristupovať, môžu vytvoriť horizontálne oddiely v užívateľskom priestore namiesto delegovania tejto práce na databázu. Tento proces sa nazýva „sharding na úrovni aplikácie“ (rozdelenie na úrovni aplikácie).

Bohužiaľ, tento názov často vytvára mylnú predstavu, že sharding žije v aplikačných službách. V skutočnosti môže byť implementovaná ako samostatná vrstva pred databázou. V závislosti od rastu údajov a iterácií schémy môžu byť požiadavky na zdieľanie pomerne zložité. Niektoré stratégie môžu ťažiť zo schopnosti iterácie bez toho, aby ste museli premiestňovať aplikačné servery.

O databázach by to malo vedieť viac vývojárov
Príklad architektúry, v ktorej sú aplikačné servery oddelené od shardingovej služby

Presunutie shardingu do samostatnej služby rozširuje možnosti používania rôznych stratégií shardingu bez potreby premiestňovania aplikácií. Vitess je príkladom takéhoto systému shardingu na aplikačnej úrovni. Vites poskytuje horizontálne sharding pre MySQL a umožňuje klientom pripojiť sa k nemu prostredníctvom protokolu MySQL. Systém segmentuje dáta do rôznych MySQL uzlov, ktoré o sebe nič nevedia.

Autoinkrementácia môže byť nebezpečná

AUTOINCREMENT je bežný spôsob generovania primárnych kľúčov. Často sa vyskytujú prípady, keď sa ako generátory ID používajú databázy a databáza obsahuje tabuľky určené na generovanie identifikátorov. Existuje niekoľko dôvodov, prečo generovanie primárnych kľúčov pomocou automatického inkrementovania nie je ani zďaleka ideálne:

  • V distribuovanej databáze je automatické zvyšovanie vážnym problémom. Na vygenerovanie ID je potrebný globálny zámok. Namiesto toho môžete vygenerovať UUID: to nevyžaduje interakciu medzi rôznymi uzlami databázy. Automatické zvyšovanie pomocou zámkov môže viesť k sporom a výrazne znížiť výkon vložiek v distribuovaných situáciách. Niektoré DBMS (napríklad MySQL) môžu vyžadovať špeciálnu konfiguráciu a starostlivejšiu pozornosť na správnu organizáciu replikácie master-master. A pri konfigurácii je ľahké robiť chyby, čo povedie k zlyhaniam nahrávania.
  • Niektoré databázy majú rozdeľovacie algoritmy založené na primárnych kľúčoch. Po sebe idúce ID môžu viesť k nepredvídateľným aktívnym miestam a zvýšenému zaťaženiu niektorých oddielov, zatiaľ čo iné zostávajú nečinné.
  • Primárny kľúč je najrýchlejší spôsob prístupu k riadku v databáze. S lepšími spôsobmi identifikácie záznamov môžu sekvenčné ID zmeniť najdôležitejší stĺpec v tabuľkách na zbytočný stĺpec plný nezmyselných hodnôt. Preto vždy, keď je to možné, zvoľte globálne jedinečný a prirodzený primárny kľúč (napr. používateľské meno).

Pred rozhodnutím o prístupe zvážte vplyv automatického zvyšovania ID a UUID na indexovanie, rozdelenie a zdieľanie.

Zastarané údaje môžu byť užitočné a nevyžadujú uzamknutie

Multiversion Concurrency Control (MVCC) implementuje mnohé z požiadaviek na konzistenciu, ktoré boli stručne uvedené vyššie. Niektoré databázy (napríklad Postgres, Spanner) používajú MVCC na „kŕmenie“ transakcií snímkami – staršími verziami databázy. Snapshot transakcie môžu byť tiež serializované, aby sa zabezpečila konzistentnosť. Pri čítaní zo starej snímky sa čítajú neaktuálne údaje.

Čítanie mierne zastaraných údajov môže byť užitočné napríklad pri generovaní analytiky z údajov alebo pri výpočte približných súhrnných hodnôt.

Prvou výhodou práce so staršími údajmi je nízka latencia (najmä ak je databáza distribuovaná v rôznych geografických oblastiach). Druhým je, že transakcie len na čítanie sú bez zámku. To je významná výhoda pre aplikácie, ktoré veľa čítajú, pokiaľ dokážu spracovať zastarané dáta.

O databázach by to malo vedieť viac vývojárov
Aplikačný server číta údaje z lokálnej repliky, ktorá je 5 sekúnd neaktuálna, aj keď je najnovšia verzia dostupná na druhej strane Tichého oceánu.

DBMS automaticky vyčistia staršie verzie a v niektorých prípadoch vám to umožňujú na požiadanie. Používateľom to umožňuje napríklad Postgres VACUUM na požiadanie a tiež pravidelne vykonáva túto operáciu automaticky. Spanner spúšťa zberač odpadu, aby sa zbavil snímok starších ako jedna hodina.

Akékoľvek časové zdroje podliehajú skresleniu

Najlepšie stráženým tajomstvom v informatike je, že všetky rozhrania API na načasovanie klamú. V skutočnosti naše stroje nepoznajú presný aktuálny čas. Počítače obsahujú kryštály kremeňa, ktoré generujú vibrácie, ktoré sa používajú na udržanie času. Nie sú však dostatočne presné a môžu byť vpredu/zaostávať za presným časom. Zmena môže dosiahnuť 20 sekúnd za deň. Preto musíme čas na našich počítačoch pravidelne synchronizovať so sieťovým.

Na synchronizáciu sa používajú servery NTP, ale samotný proces synchronizácie podlieha sieťovým oneskoreniam. Dokonca aj synchronizácia so serverom NTP v rovnakom dátovom centre trvá nejaký čas. Je jasné, že práca s verejným NTP serverom môže viesť k ešte väčšiemu skresleniu.

Atómové hodiny a ich GPS náprotivky sú lepšie na určenie aktuálneho času, ale sú drahé a vyžadujú zložité nastavenie, takže ich nemožno namontovať na každé auto. Z tohto dôvodu dátové centrá používajú viacúrovňový prístup. Atómové a/alebo GPS hodiny ukazujú presný čas, po ktorom je vysielaný do iných strojov cez sekundárne servery. To znamená, že každý stroj zažije určitý posun od presného času.

Situáciu zhoršuje skutočnosť, že aplikácie a databázy sú často umiestnené na rôznych strojoch (ak nie v rôznych dátových centrách). Čas sa teda bude líšiť nielen na DB uzloch distribuovaných na rôznych strojoch. Iné to bude aj na aplikačnom serveri.

Google TrueTime má úplne iný prístup. Väčšina ľudí verí, že pokrok spoločnosti Google v tomto smere sa vysvetľuje banálnym prechodom na atómové hodiny a hodiny GPS, ale to je len časť celkového obrazu. TrueTime funguje takto:

  • TrueTime využíva dva rôzne zdroje: GPS a atómové hodiny. Tieto hodinky majú nekorelované režimy zlyhania. [podrobnosti nájdete na strane 5 tu - približne. preklad.), takže ich spoločné používanie zvyšuje spoľahlivosť.
  • TrueTime má nezvyčajné API. Vracia čas ako interval so zabudovanou chybou merania a neistotou. Aktuálny časový okamih je niekde medzi hornou a dolnou hranicou intervalu. Spanner, distribuovaná databáza Google, jednoducho čaká, kým sa dá bezpečne povedať, že aktuálny čas je mimo rozsahu. Táto metóda vnáša do systému určitú latenciu, najmä ak je neistota na masteroch vysoká, ale zabezpečuje správnosť aj v globálne distribuovanej situácii.

O databázach by to malo vedieť viac vývojárov
Komponenty Spanner používajú TrueTime, kde TT.now() vracia interval, takže Spanner jednoducho spí až do bodu, kedy si môže byť istý, že aktuálny čas prešiel určitým bodom.

Znížená presnosť pri určovaní aktuálneho času znamená predĺženie trvania operácií Spanner a zníženie výkonu. Preto je dôležité zachovať čo najvyššiu presnosť, aj keď nie je možné získať úplne presné hodinky.

Oneskorenie má veľa významov

Ak sa spýtate tucta odborníkov na to, čo je meškanie, pravdepodobne dostanete rôzne odpovede. V DBMS sa latencia často nazýva „latencia databázy“ a líši sa od toho, čo vníma klient. Faktom je, že klient pozoruje súčet oneskorenia siete a oneskorenia databázy. Schopnosť izolovať typ latencie je rozhodujúca pri ladení rastúcich problémov. Pri zhromažďovaní a zobrazovaní metrík sa vždy snažte sledovať oba typy.

Požiadavky na výkon by sa mali vyhodnotiť pre konkrétnu transakciu

Niekedy sú výkonové charakteristiky DBMS a jej obmedzenia špecifikované z hľadiska priepustnosti zápisu/čítania a latencie. Toto poskytuje všeobecný prehľad kľúčových parametrov systému, ale pri hodnotení výkonu nového DBMS je oveľa komplexnejším prístupom samostatné vyhodnotenie kritických operácií (pre každý dotaz a/alebo transakciu). Príklady:

  • Priepustnosť zápisu a latencia pri vkladaní nového riadka do tabuľky X (s 50 miliónmi riadkov) so špecifikovanými obmedzeniami a odsadením riadkov v súvisiacich tabuľkách.
  • Oneskorenie zobrazenia priateľov priateľov určitého používateľa, keď je priemerný počet priateľov 500.
  • Latencia pri získavaní 100 najlepších záznamov z histórie používateľa, keď používateľ sleduje 500 iných používateľov s X záznamami za hodinu.

Hodnotenie a experimentovanie môže zahŕňať takéto kritické prípady, kým si nie ste istí, že databáza spĺňa požiadavky na výkon. Podobné pravidlo zohľadňuje toto rozdelenie aj pri zhromažďovaní metrík latencie a určovaní SLO.

Buďte si vedomí vysokej mohutnosti pri zhromažďovaní metrík pre každú operáciu. Použite protokoly, zhromažďovanie udalostí alebo distribuované sledovanie na získanie vysokovýkonných ladiacich údajov. V článku "Chcete ladiť latenciu?» môžete sa zoznámiť s metodikami ladenia oneskorenia.

Vnorené transakcie môžu byť nebezpečné

Nie každý DBMS podporuje vnorené transakcie, ale keď áno, takéto transakcie môžu viesť k neočakávaným chybám, ktoré nie je vždy ľahké odhaliť (to znamená, že by malo byť zrejmé, že existuje nejaký druh anomálie).

Môžete sa vyhnúť používaniu vnorených transakcií pomocou klientskych knižníc, ktoré ich dokážu zistiť a obísť. Ak sa vnorené transakcie nedajú opustiť, venujte ich implementácii mimoriadnu pozornosť, aby ste predišli neočakávaným situáciám, kedy sú dokončené transakcie náhodne prerušené kvôli vnoreným transakciám.

Zapuzdrenie transakcií do rôznych vrstiev môže viesť k neočakávaným vnoreným transakciám a z hľadiska čitateľnosti kódu môže sťažiť pochopenie zámerov autora. Pozrite si nasledujúci program:

with newTransaction():
   Accounts.create("609-543-222")
   with newTransaction():
       Accounts.create("775-988-322")
       throw Rollback();

Aký bude výstup vyššie uvedeného kódu? Vráti späť obe transakcie alebo len tú vnútornú? Čo sa stane, ak sa spoliehame na viacero vrstiev knižníc, ktoré zapuzdrujú vytváranie transakcií za nás? Budeme schopní identifikovať a zlepšiť takéto prípady?

Predstavte si dátovú vrstvu s viacerými operáciami (napr. newAccount) sa už implementuje vo vlastných transakciách. Čo sa stane, ak ich spustíte ako súčasť obchodnej logiky vyššej úrovne, ktorá prebieha v rámci vlastnej transakcie? Aká by bola v tomto prípade izolácia a konzistentnosť?

function newAccount(id string) {
  with newTransaction():
      Accounts.create(id)
}

Namiesto hľadania odpovedí na takéto nekonečné otázky je lepšie vyhnúť sa vnoreným transakciám. Koniec koncov, vaša dátová vrstva môže jednoducho vykonávať operácie na vysokej úrovni bez vytvárania vlastných transakcií. Okrem toho samotná obchodná logika je schopná iniciovať transakciu, vykonávať s ňou operácie, zaviazať alebo zrušiť transakciu.

function newAccount(id string) {
   Accounts.create(id)
}
// In main application:
with newTransaction():
   // Read some data from database for configuration.
   // Generate an ID from the ID service.
   Accounts.create(id)
   Uploads.create(id) // create upload queue for the user.

Transakcie by nemali byť viazané na stav aplikácie

Niekedy je lákavé použiť stav aplikácie v transakciách na zmenu určitých hodnôt alebo vyladenie parametrov dotazu. Najdôležitejšou nuansou, ktorú treba zvážiť, je správny rozsah aplikácie. Klienti často reštartujú transakcie, keď sa vyskytnú problémy so sieťou. Ak transakcia potom závisí od stavu, ktorý mení nejaký iný proces, môže si vybrať nesprávnu hodnotu v závislosti od možnosti dátového závodu. Transakcie musia brať do úvahy riziko pretekania údajov v aplikácii.

var seq int64
with newTransaction():
    newSeq := atomic.Increment(&seq)
    Entries.query(newSeq)
    // Other operations...

Vyššie uvedená transakcia zvýši poradové číslo vždy, keď sa vykoná, bez ohľadu na konečný výsledok. Ak odovzdanie zlyhá kvôli problémom so sieťou, požiadavka sa pri opätovnom pokuse vykoná s iným poradovým číslom.

Plánovač dopytov vám môže povedať veľa o databáze

Plánovač dotazov určuje, ako bude dotaz vykonaný v databáze. Tiež analyzujú požiadavky a optimalizujú ich pred ich odoslaním. Plánovači môžu poskytnúť len niektoré možné odhady na základe signálov, ktoré majú k dispozícii. Aká je napríklad najlepšia metóda vyhľadávania pre nasledujúci dopyt?

SELECT * FROM articles where author = "rakyll" order by title;

Výsledky je možné získať dvoma spôsobmi:

  • Kompletné skenovanie tabuľky: Môžete si pozrieť každý záznam v tabuľke a vrátiť články so zodpovedajúcim menom autora a potom si ich objednať.
  • Indexové skenovanie: Index môžete použiť na nájdenie zodpovedajúcich ID, získanie týchto riadkov a ich zoradenie.

Úlohou plánovača dotazov je určiť, ktorá stratégia je najlepšia. Stojí za zváženie, že plánovače dotazov majú len obmedzené prediktívne schopnosti. To môže viesť k zlým rozhodnutiam. DBA alebo vývojári ich môžu použiť na diagnostiku a doladenie nedostatočne výkonných dopytov. Nové verzie DBMS môžu konfigurovať plánovače dotazov a autodiagnostika môže pomôcť pri aktualizácii databázy, ak nová verzia vedie k problémom s výkonom. Pomalé protokoly dotazov, hlásenia o problémoch s oneskorením alebo štatistika času vykonávania môžu pomôcť identifikovať dotazy, ktoré vyžadujú optimalizáciu.

Niektoré metriky prezentované plánovačom dotazov môžu podliehať šumu (najmä pri odhadovaní latencie alebo času CPU). Dobrým doplnkom plánovačov sú nástroje na sledovanie a sledovanie cesty vykonávania. Umožňujú vám diagnostikovať takéto problémy (žiaľ, nie všetky DBMS poskytujú takéto nástroje).

Online migrácia je náročná, ale možná

Online migrácia, živá migrácia alebo migrácia v reálnom čase znamená prechod z jednej databázy do druhej bez výpadkov alebo poškodenia údajov. Živá migrácia sa ľahšie uskutoční, ak sa prechod uskutoční v rámci rovnakého systému DBMS/engine. Situácia sa komplikuje, keď je potrebné prejsť na nový DBMS s odlišnými požiadavkami na výkon a schému.

Existujú rôzne modely online migrácie. Tu je jeden z nich:

  • Povoliť dvojité zadávanie v oboch databázach. Nová databáza v tejto fáze nemá všetky údaje, ale akceptuje len najnovšie údaje. Keď ste si tým istí, môžete prejsť na ďalší krok.
  • Povoliť čítanie z oboch databáz.
  • Nakonfigurujte systém tak, aby sa čítanie a zápis vykonávalo predovšetkým v novej databáze.
  • Zastavte zápis do starej databázy a pokračujte v čítaní údajov z nej. V tejto fáze nová databáza stále neobsahuje niektoré údaje. Mali by byť skopírované zo starej databázy.
  • Stará databáza je len na čítanie. Skopírujte chýbajúce údaje zo starej databázy do novej. Po dokončení migrácie prepnite cesty k novej databáze a zastavte starú a odstráňte ju zo systému.

Pre ďalšie informácie odporúčam kontaktovať článok, ktorá podrobne popisuje migračnú stratégiu spoločnosti Stripe založenú na tomto modeli.

Výrazný nárast v databáze znamená zvýšenie nepredvídateľnosti

Rast databázy vedie k nepredvídateľným problémom spojeným s jej rozsahom. Čím viac vieme o vnútornej štruktúre databázy, tým lepšie vieme predpovedať jej rozsah. Niektoré momenty sa však stále nedajú predvídať.
S rastom základne môžu byť predchádzajúce predpoklady a očakávania týkajúce sa objemu dát a požiadaviek na šírku pásma siete zastarané. Vtedy vyvstáva otázka veľkých prepracovaní dizajnu, rozsiahlych prevádzkových vylepšení, prehodnotenia nasadenia alebo migrácie na iné DBMS, aby sa predišlo potenciálnym problémom.

Nemyslite si však, že je potrebná len výborná znalosť vnútornej štruktúry existujúcej databázy. Nové váhy so sebou prinesú nové nepoznané. Nepredvídateľné bolestivé body, nerovnomerná distribúcia údajov, neočakávané problémy so šírkou pásma a hardvérom, neustále sa zvyšujúca návštevnosť a nové segmenty siete vás prinútia prehodnotiť svoj databázový prístup, dátový model, model nasadenia a veľkosť databázy.

...

V čase, keď som začal uvažovať o publikovaní tohto článku, bolo na mojom pôvodnom zozname už päť ďalších položiek. Potom prišlo obrovské množstvo nové nápady o tom, čo ešte možno pokryť. Preto sa článok dotýka najmenej zjavných problémov, ktoré si vyžadujú maximálnu pozornosť. To však neznamená, že téma bola vyčerpaná a už sa k nej v budúcich materiáloch nevrátim a nebudem robiť zmeny v tej súčasnej.

PS

Prečítajte si aj na našom blogu:

Zdroj: hab.com

Pridať komentár