Več razvijalcev bi moralo vedeti to o bazah podatkov

Opomba. prevod: Jaana Dogan je izkušena inženirka pri Googlu, ki se trenutno ukvarja z opazljivostjo proizvodnih storitev podjetja, napisanih v Go. V tem članku, ki je pridobil veliko popularnost med angleško govorečo publiko, je v 17 točkah zbrala pomembne tehnične podrobnosti o DBMS (in včasih porazdeljenih sistemih na splošno), ki jih je koristno upoštevati razvijalcem velikih/zahtevnih aplikacij.

Več razvijalcev bi moralo vedeti to o bazah podatkov

Velika večina računalniških sistemov spremlja svoje stanje in zato potrebuje nekakšen sistem za shranjevanje podatkov. Dolgo časa sem nabiral znanje o bazah podatkov, ob tem pa delal napake pri oblikovanju, ki so privedle do izgube podatkov in izpadov. V sistemih, ki obdelujejo velike količine informacij, so baze podatkov v središču sistemske arhitekture in delujejo kot ključni element pri izbiri optimalne rešitve. Kljub dejstvu, da se delu baze podatkov posveča velika pozornost, so težave, ki jih razvijalci aplikacij poskušajo predvideti, pogosto le vrh ledene gore. V tej seriji člankov delim nekaj idej, ki bodo koristne za razvijalce, ki niso specializirani na tem področju.

  1. Srečo imate, če 99,999 % časa omrežje ne povzroča težav.
  2. KISLINA pomeni veliko različnih stvari.
  3. Vsaka zbirka podatkov ima svoje mehanizme za zagotavljanje doslednosti in izolacije.
  4. Optimistična blokada priskoči na pomoč, ko je težko ohraniti običajno.
  5. Poleg umazanih branj in izgube podatkov obstajajo tudi druge anomalije.
  6. Baza podatkov in uporabnik se ne strinjata vedno o poteku dejanj.
  7. Sharding na ravni aplikacije je mogoče premakniti izven aplikacije.
  8. Samodejno povečanje je lahko nevarno.
  9. Zastareli podatki so lahko uporabni in jih ni treba zakleniti.
  10. Izkrivljanja so značilna za vse časovne vire.
  11. Zamuda ima veliko pomenov.
  12. Zahteve glede uspešnosti je treba oceniti za določeno transakcijo.
  13. Ugnezdene transakcije so lahko nevarne.
  14. Transakcije ne smejo biti vezane na stanje aplikacije.
  15. Načrtovalci poizvedb vam lahko povedo veliko o bazah podatkov.
  16. Spletna migracija je težka, a mogoča.
  17. Znatno povečanje baze podatkov pomeni povečanje nepredvidljivosti.

Rad bi se zahvalil Emmanuelu Odekeju, Reinu Henrichsu in drugim za povratne informacije o prejšnji različici tega članka.

Srečo imate, če 99,999 % časa omrežje ne povzroča težav.

Ostaja vprašanje, kako zanesljive so sodobne omrežne tehnologije in kako pogosto sistemi ne delujejo zaradi okvar omrežja. Informacije o tem vprašanju so redke in v raziskavah pogosto prevladujejo velike organizacije s specializiranimi mrežami, opremo in osebjem.

S stopnjo razpoložljivosti 99,999 % za Spanner (Googlova globalno distribuirana baza podatkov) Google trdi, da le 7,6% težave so povezane z omrežjem. Hkrati podjetje svojo specializirano mrežo imenuje "glavni steber" visoke razpoložljivosti. Študij Bailis in Kingsbury, ki je bil izveden leta 2014, izpodbija enega od »napačne predstave o porazdeljenem računalništvu«, ki ga je leta 1994 oblikoval Peter Deutsch. Je omrežje res zanesljivo?

Celovite raziskave zunaj velikanskih podjetij, ki se izvajajo za širši internet, preprosto ne obstajajo. Prav tako ni dovolj podatkov glavnih igralcev o tem, kolikšen odstotek težav njihovih strank je povezanih z omrežjem. Dobro poznamo izpade v omrežju velikih ponudnikov v oblaku, ki lahko za več ur uničijo celoten kos interneta preprosto zato, ker gre za odmevne dogodke, ki prizadenejo veliko število ljudi in podjetij. Izpadi omrežja lahko povzročijo težave v veliko več primerih, tudi če niso vsi ti primeri v središču pozornosti. Tudi naročniki storitev v oblaku ne vedo ničesar o vzrokih težav. Če pride do okvare, jo je skoraj nemogoče pripisati omrežni napaki na strani ponudnika storitev. Zanje so storitve tretjih oseb črne skrinjice. Nemogoče je oceniti vpliv, ne da bi bili velik ponudnik storitev.

Glede na to, kaj veliki igralci poročajo o svojih sistemih, lahko rečemo, da imate srečo, če težave z omrežjem predstavljajo le majhen odstotek morebitnih izpadov. Omrežne komunikacije še vedno trpijo zaradi tako vsakdanjih stvari, kot so okvare strojne opreme, spremembe topologije, spremembe upravne konfiguracije in izpadi električne energije. Pred kratkim sem bil presenečen, ko sem izvedel, da je bil dodan seznam možnih težav ugrizi morskega psa (ja, prav ste slišali).

ACID pomeni veliko različnih stvari

Akronim ACID pomeni Atomicity, Consistency, Isolation, Reliability. Te lastnosti transakcij so namenjene zagotavljanju njihove veljavnosti v primeru okvar, napak, okvar strojne opreme itd. Brez ACID ali podobnih shem bi razvijalci aplikacij težko razlikovali med tem, za kaj so odgovorni, in za kaj je odgovorna baza podatkov. Večina relacijskih transakcijskih baz podatkov poskuša biti združljivih s standardom ACID, vendar so novi pristopi, kot je NoSQL, povzročili nastanek številnih baz podatkov brez transakcij ACID, ker je njihovo izvajanje drago.

Ko sem prvič vstopil v industrijo, je naš tehnični vodja govoril o tem, kako pomemben je koncept ACID. Če smo pošteni, ACID velja za grob opis in ne za strog standard izvajanja. Danes se mi zdi predvsem uporaben, ker odpira določeno kategorijo vprašanj (in predlaga vrsto možnih rešitev).

Vsak DBMS ni skladen s standardom ACID; Hkrati implementacije baz podatkov, ki podpirajo ACID, razumejo nabor zahtev drugače. Eden od razlogov, zakaj so implementacije ACID neenakomerne, je posledica številnih kompromisov, ki jih je treba narediti za implementacijo zahtev ACID. Ustvarjalci lahko predstavijo svoje zbirke podatkov kot skladne z ACID, vendar se lahko razlaga robnih primerov dramatično razlikuje, prav tako mehanizem za obravnavanje "malo verjetnih" dogodkov. Vsaj razvijalci lahko pridobijo visoko raven razumevanja zapletenosti osnovnih izvedb, da pridobijo pravilno razumevanje njihovega posebnega vedenja in kompromisov pri načrtovanju.

Razprava o tem, ali MongoDB izpolnjuje zahteve ACID, se nadaljuje tudi po izdaji različice 4. MongoDB že dolgo ni bil podprt sečnja, čeprav so bili podatki privzeto posredovani na disk največ enkrat vsakih 60 sekund. Predstavljajte si naslednji scenarij: aplikacija objavi dva zapisa (w1 in w2). MongoDB uspešno shrani w1, vendar je w2 izgubljen zaradi okvare strojne opreme.

Več razvijalcev bi moralo vedeti to o bazah podatkov
Diagram, ki ponazarja scenarij. MongoDB se zruši, preden lahko zapiše podatke na disk

Zavezanost na disk je drag postopek. Z izogibanjem pogostim zavezam razvijalci izboljšajo zmogljivost snemanja na račun zanesljivosti. MongoDB trenutno podpira beleženje, vendar lahko umazano pisanje še vedno vpliva na celovitost podatkov, saj se dnevniki privzeto zajamejo vsakih 100 ms. To pomeni, da je podoben scenarij še vedno možen za dnevnike in spremembe, predstavljene v njih, čeprav je tveganje veliko manjše.

Vsaka zbirka podatkov ima svoje mehanizme doslednosti in izolacije

Od zahtev ACID se doslednost in izolacija ponašata z največjim številom različnih izvedb, ker je obseg kompromisov širši. Povedati je treba, da sta doslednost in izolacija precej dragi funkciji. Zahtevajo usklajevanje in povečujejo konkurenco za doslednost podatkov. Kompleksnost problema se znatno poveča, ko je treba bazo podatkov vodoravno razširiti na več podatkovnih centrov (še posebej, če se nahajajo v različnih geografskih regijah). Doseganje visoke ravni konsistentnosti je zelo težko, saj tudi zmanjšuje razpoložljivost in povečuje segmentacijo omrežja. Za bolj splošno razlago tega pojava vam svetujem, da se obrnete na CAP izrek. Prav tako je treba omeniti, da lahko aplikacije obvladajo majhne količine neskladnosti, programerji pa lahko dovolj dobro razumejo nianse težave, da v aplikaciji implementirajo dodatno logiko za obravnavo neskladnosti, ne da bi se pri tem močno zanašali na bazo podatkov.

DBMS pogosto zagotavljajo različne ravni izolacije. Razvijalci aplikacij lahko izberejo najučinkovitejšo na podlagi svojih preferenc. Nizka izolacija omogoča večjo hitrost, vendar tudi povečuje tveganje podatkovne tekme. Visoka izolacija zmanjša to verjetnost, a upočasni delo in lahko povzroči konkurenco, ki bo povzročila takšne zavore v bazi, da se začnejo okvare.

Več razvijalcev bi moralo vedeti to o bazah podatkov
Pregled obstoječih modelov sočasnosti in odnosov med njimi

Standard SQL določa le štiri izolacijske nivoje, čeprav jih je v teoriji in praksi veliko več. Jepson.io ponuja odličen pregled obstoječih modelov sočasnosti. Google Spanner na primer zagotavlja zunanjo možnost serializacije s sinhronizacijo ure, in čeprav je to strožja izolacijska plast, ni definirana v standardnih izolacijskih plasteh.

Standard SQL omenja naslednje ravni izolacije:

  • Serializable (najstrožje in drago): Izvedba, ki jo je mogoče serializirati, ima enak učinek kot nekatera zaporedna izvedba transakcije. Zaporedna izvedba pomeni, da se vsaka naslednja transakcija začne šele po zaključku prejšnje. Treba je opozoriti, da je raven Serializable pogosto implementiran kot tako imenovana izolacija posnetkov (na primer v Oracle) zaradi razlik v interpretaciji, čeprav sama izolacija posnetkov ni predstavljena v standardu SQL.
  • Ponovljivo branje: Nedodeljeni zapisi v trenutni transakciji so na voljo trenutni transakciji, vendar spremembe, ki jih naredijo druge transakcije (kot so nove vrstice) ni vidno.
  • Preberi zavezano: Nedodeljeni podatki niso na voljo za transakcije. V tem primeru lahko transakcije vidijo samo odobrene podatke in lahko pride do fantomskih branj. Če transakcija vstavi in ​​potrdi nove vrstice, jih bo trenutna transakcija ob poizvedbi lahko videla.
  • Preberi nezavezano (najmanj stroga in draga raven): umazano branje je dovoljeno, transakcije lahko vidijo neobvezne spremembe, ki so jih naredile druge transakcije. V praksi je ta raven lahko uporabna za grobe ocene, kot so poizvedbe COUNT(*) na mizi.

Raven Serializable zmanjšuje tveganje podatkovnih tekem, hkrati pa je najdražji za izvedbo in povzroča največjo konkurenčno obremenitev sistema. Druge ravni izolacije je lažje implementirati, vendar povečajo verjetnost podatkovnih dirk. Nekateri DBMS vam omogočajo nastavitev ravni izolacije po meri, drugi imajo močne nastavitve in niso podprte vse ravni.

Podpora za ravni izolacije se pogosto oglašuje v danem DBMS, vendar le natančna študija njegovega vedenja lahko razkrije, kaj se dejansko dogaja.

Več razvijalcev bi moralo vedeti to o bazah podatkov
Pregled anomalij sočasnosti na različnih ravneh izolacije za različne DBMS

Martin Kleppmann v svojem projektu pustovanje Primerja različne ravni izolacije, govori o anomalijah sočasnosti in o tem, ali je baza podatkov sposobna upoštevati določeno raven izolacije. Kleppmannova raziskava kaže, kako različno razmišljajo razvijalci baz podatkov o stopnjah izolacije.

Optimistična blokada priskoči na pomoč, ko je težko ohraniti običajno.

Blokiranje je lahko zelo drago, ne le zato, ker povečuje konkurenco v bazi podatkov, ampak tudi zato, ker zahteva, da se aplikacijski strežniki nenehno povezujejo z bazo podatkov. Segmentacija omrežja lahko poslabša situacije ekskluzivnega zaklepanja in povzroči zastoje, ki jih je težko prepoznati in razrešiti. V primerih, ko ekskluzivno zaklepanje ni primerno, pomaga optimistično zaklepanje.

Optimistična ključavnica je metoda, pri kateri pri branju niza upošteva njegovo različico, kontrolno vsoto ali čas zadnje spremembe. To vam omogoča, da zagotovite, da ni atomične spremembe različice, preden spremenite vnos:

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

V tem primeru posodabljanje tabele products ne bo izvedeno, če je druga operacija predhodno spremenila to vrstico. Če v tej vrstici ni bila izvedena nobena druga operacija, bo prišlo do spremembe za eno vrstico in lahko rečemo, da je bila posodobitev uspešna.

Poleg umazanih branj in izgube podatkov obstajajo tudi druge anomalije

Ko gre za doslednost podatkov, je poudarek na možnostih dirkalnih pogojev, ki lahko vodijo do umazanih branj in izgube podatkov. Vendar se anomalije podatkov ne ustavijo pri tem.

Eden od primerov takih anomalij je popačenje zapisa (napišite poševnice). Izkrivljanja je težko zaznati, ker jih običajno ne iščemo aktivno. Niso posledica umazanih branj ali izgube podatkov, temveč kršitev logičnih omejitev, ki so postavljene na podatke.

Na primer, razmislimo o aplikaciji za spremljanje, ki zahteva, da je en operater ves čas dežuran:

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;

V zgornji situaciji bo prišlo do rekordne poškodbe, če sta obe transakciji uspešno izvedeni. Čeprav ni bilo umazanih branj ali izgube podatkov, je bila celovitost podatkov ogrožena: zdaj sta dežurni dve osebi hkrati.

Izolacija, ki jo je mogoče serializirati, oblikovanje sheme ali omejitve baze podatkov lahko pomagajo odpraviti poškodbe pri zapisovanju. Razvijalci morajo biti sposobni prepoznati takšne anomalije med razvojem, da se jim izognejo v proizvodnji. Hkrati je popačenje zapisa izjemno težko iskati v kodni bazi. Še posebej v velikih sistemih, ko so različne razvojne ekipe odgovorne za izvajanje funkcij na podlagi istih tabel in se ne strinjajo glede posebnosti dostopa do podatkov.

Baza podatkov in uporabnik se ne strinjata vedno, kaj storiti

Ena od ključnih lastnosti baz podatkov je jamstvo za vrstni red izvajanja, vendar ta vrstni red sam morda ni pregleden za razvijalca programske opreme. Podatkovne baze izvajajo transakcije v vrstnem redu, kot so prejete, ne v vrstnem redu, kot ga načrtujejo programerji. Vrstni red transakcij je težko predvideti, še posebej v zelo obremenjenih vzporednih sistemih.

Med razvojem, zlasti pri delu s knjižnicami, ki ne blokirajo, lahko slab slog in slaba berljivost povzročita, da uporabniki verjamejo, da se transakcije izvajajo zaporedno, čeprav bi v resnici lahko prispele v bazo podatkov v poljubnem vrstnem redu.

Na prvi pogled se v spodnjem programu T1 in T2 kličeta zaporedno, če pa sta ti funkciji neblokirni in takoj vrneta rezultat v obliki Obljuba, potem bo vrstni red klicev določen glede na trenutke, ko so vstopili v bazo podatkov:

rezultat1 = T1() // pravi rezultati so obljube
rezultat2 = T2()

Če je zahtevana atomičnost (to je, da morajo biti vse operacije dokončane ali prekinjene) in je zaporedje pomembno, potem je treba operaciji T1 in T2 izvesti znotraj ene transakcije.

Sharding na ravni aplikacije je mogoče premakniti izven aplikacije

Sharding je metoda vodoravnega razdeljevanja baze podatkov. Nekatere zbirke podatkov lahko samodejno vodoravno razdelijo podatke, medtem ko druge ne morejo ali pa tega ne obvladajo zelo dobro. Ko lahko podatkovni arhitekti/razvijalci natančno predvidijo, kako bodo do podatkov dostopali, lahko ustvarijo vodoravne particije v uporabniškem prostoru, namesto da bi to delo prenesli na bazo podatkov. Ta postopek se imenuje "sharding na ravni aplikacije" (sharding na ravni aplikacije).

Na žalost to ime pogosto ustvarja napačno predstavo, da razdeljevanje živi v aplikacijskih storitvah. Pravzaprav ga je mogoče implementirati kot ločen sloj pred bazo podatkov. Odvisno od rasti podatkov in iteracij sheme lahko postanejo zahteve za razdeljevanje precej zapletene. Nekaterim strategijam lahko koristi možnost iteracije, ne da bi morali znova namestiti aplikacijske strežnike.

Več razvijalcev bi moralo vedeti to o bazah podatkov
Primer arhitekture, v kateri so aplikacijski strežniki ločeni od storitve razdeljevanja

Premik razdeljevanja v ločeno storitev razširi zmožnost uporabe različnih strategij razdeljevanja brez potrebe po ponovnem nameščanju aplikacij. Vitess je primer takšnega sistema razčlenjevanja na ravni aplikacije. Vitess zagotavlja horizontalno razčlenjevanje za MySQL in strankam omogoča povezavo z njim prek protokola MySQL. Sistem segmentira podatke v različna vozlišča MySQL, ki drug o drugem ne vedo ničesar.

Samodejno povečanje je lahko nevarno

AUTOINCREMENT je običajen način za ustvarjanje primarnih ključev. Pogosto so primeri, ko se baze podatkov uporabljajo kot generatorji ID-jev, baza podatkov pa vsebuje tabele, namenjene ustvarjanju identifikatorjev. Obstaja več razlogov, zakaj generiranje primarnih ključev s samodejnim povečevanjem še zdaleč ni idealno:

  • V porazdeljeni bazi podatkov je samodejno povečevanje resen problem. Za ustvarjanje ID-ja je potrebno globalno zaklepanje. Namesto tega lahko ustvarite UUID: to ne zahteva interakcije med različnimi vozlišči baze podatkov. Samodejno povečevanje z zaklepanji lahko privede do spora in znatno zmanjša zmogljivost vstavkov v porazdeljenih situacijah. Nekateri DBMS-ji (na primer MySQL) lahko zahtevajo posebno konfiguracijo in več pozornosti za pravilno organizacijo podvajanja master-master. In pri konfiguraciji je enostavno narediti napake, kar bo povzročilo napake pri snemanju.
  • Nekatere baze podatkov imajo algoritme za particioniranje, ki temeljijo na primarnih ključih. Zaporedni ID-ji lahko privedejo do nepredvidljivih vročih točk in povečane obremenitve nekaterih particij, medtem ko druge ostanejo nedejavne.
  • Primarni ključ je najhitrejši način za dostop do vrstice v bazi podatkov. Z boljšimi načini prepoznavanja zapisov lahko zaporedni ID-ji spremenijo najpomembnejši stolpec v tabelah v neuporaben stolpec, napolnjen z nesmiselnimi vrednostmi. Zato vas prosimo, da, če je le mogoče, izberete globalno edinstven in naraven primarni ključ (npr. uporabniško ime).

Preden se odločite za pristop, razmislite o vplivu samodejnega povečevanja ID-jev in UUID-jev na indeksiranje, particioniranje in razčlenjevanje.

Zastareli podatki so lahko uporabni in jih ni treba zakleniti

Multiversion Concurrency Control (MVCC) izvaja številne zahteve skladnosti, ki so bile na kratko obravnavane zgoraj. Nekatere zbirke podatkov (na primer Postgres, Spanner) uporabljajo MVCC za »napajanje« transakcij s posnetki – starejšimi različicami baze podatkov. Transakcije posnetkov je mogoče tudi serializirati, da se zagotovi doslednost. Pri branju s starega posnetka se preberejo zastareli podatki.

Branje nekoliko zastarelih podatkov je lahko koristno, na primer pri ustvarjanju analitike iz podatkov ali pri izračunu približnih skupnih vrednosti.

Prva prednost dela s podedovanimi podatki je nizka zakasnitev (še posebej, če je baza podatkov porazdeljena po različnih geografskih območjih). Drugič, transakcije samo za branje so brez zaklepanja. To je pomembna prednost za aplikacije, ki veliko berejo, če lahko obdelujejo zastarele podatke.

Več razvijalcev bi moralo vedeti to o bazah podatkov
Aplikacijski strežnik bere podatke iz lokalne replike, ki je 5 sekund zastarela, tudi če je najnovejša različica na voljo na drugi strani Tihega oceana

DBMS-ji samodejno očistijo starejše različice in vam v nekaterih primerih to omogočijo na zahtevo. Na primer, Postgres uporabnikom omogoča VACUUM na zahtevo in to operacijo občasno izvaja samodejno. Spanner zažene zbiralnik smeti, da se znebi posnetkov, starejših od ene ure.

Kadarkoli so viri podvrženi izkrivljanju

Najbolj varovana skrivnost računalništva je, da vsi časovni API-ji lažejo. Pravzaprav naši stroji ne poznajo točnega trenutnega časa. Računalniki vsebujejo kristale kremena, ki ustvarjajo vibracije, ki se uporabljajo za beleženje časa. Vendar pa niso dovolj natančni in lahko prehitevajo/zaostajajo za točnim časom. Premik lahko doseže 20 sekund na dan. Zato moramo čas na naših računalnikih občasno sinhronizirati z omrežnim.

Za sinhronizacijo se uporabljajo strežniki NTP, vendar je sam proces sinhronizacije podvržen omrežnim zamudam. Tudi sinhronizacija s strežnikom NTP v istem podatkovnem centru traja nekaj časa. Jasno je, da lahko delo z javnim strežnikom NTP povzroči še večje izkrivljanje.

Atomske ure in njihovi analogi GPS so boljši za določanje trenutnega časa, vendar so dragi in zahtevajo zapleteno nastavitev, zato jih ni mogoče namestiti v vsak avto. Zaradi tega podatkovni centri uporabljajo stopenjski pristop. Atomske in/ali GPS ure prikazujejo točen čas, po katerem se prek sekundarnih strežnikov oddaja drugim napravam. To pomeni, da bo vsak stroj doživel določen odmik od točnega časa.

Situacijo otežuje dejstvo, da so aplikacije in baze podatkov pogosto na različnih računalnikih (če ne v različnih podatkovnih centrih). Tako se čas ne bo razlikoval le na vozliščih DB, porazdeljenih po različnih strojih. Tudi na aplikacijskem strežniku bo drugače.

Google TrueTime uporablja popolnoma drugačen pristop. Večina ljudi meni, da je napredek Googla v tej smeri razložen z banalnim prehodom na atomske in GPS ure, vendar je to le del velike slike. Takole deluje TrueTime:

  • TrueTime uporablja dva različna vira: GPS in atomske ure. Te ure imajo nekorelirane načine napak. [za podrobnosti glejte stran 5 tukaj — pribl. prev.), zato njihova skupna uporaba poveča zanesljivost.
  • TrueTime ima nenavaden API. Vrne čas kot interval z vgrajeno merilno napako in negotovostjo. Dejanski trenutek v času je nekje med zgornjo in spodnjo mejo intervala. Spanner, Googlova porazdeljena zbirka podatkov, preprosto počaka, da lahko varno rečemo, da je trenutni čas izven dosega. Ta metoda v sistem vnese nekaj zakasnitve, zlasti če je negotovost na masterjih visoka, vendar zagotavlja pravilnost tudi v globalno porazdeljeni situaciji.

Več razvijalcev bi moralo vedeti to o bazah podatkov
Komponente Spanner uporabljajo TrueTime, kjer TT.now() vrne interval, tako da Spanner preprosto spi do točke, ko je lahko prepričan, da je trenutni čas presegel določeno točko

Zmanjšana natančnost pri določanju trenutnega časa pomeni podaljšanje trajanja operacij ključa in zmanjšanje učinkovitosti. Zato je pomembno ohraniti največjo možno natančnost, čeprav je popolnoma natančne ure nemogoče dobiti.

Zamuda ima veliko pomenov

Če vprašate ducat strokovnjakov o tem, kaj je zamuda, boste verjetno dobili različne odgovore. V DBMS se zakasnitev pogosto imenuje "zakasnitev baze podatkov" in je drugačna od tiste, ki jo zaznava odjemalec. Dejstvo je, da odjemalec opazuje vsoto zakasnitve omrežja in zakasnitve baze podatkov. Zmožnost izolacije vrste zakasnitve je kritična pri odpravljanju napak v naraščajočih težavah. Pri zbiranju in prikazovanju meritev vedno poskušajte paziti na obe vrsti.

Zahteve glede uspešnosti je treba oceniti za določeno transakcijo

Včasih so značilnosti zmogljivosti DBMS in njegove omejitve določene v smislu prepustnosti pisanja/branja in zakasnitve. To zagotavlja splošen pregled ključnih sistemskih parametrov, vendar je pri vrednotenju delovanja novega DBMS veliko bolj celovit pristop ločeno vrednotenje kritičnih operacij (za vsako poizvedbo in/ali transakcijo). Primeri:

  • Prepustnost pisanja in zakasnitev pri vstavljanju nove vrstice v tabelo X (s 50 milijoni vrstic) z določenimi omejitvami in oblazinjenjem vrstic v povezanih tabelah.
  • Zakasnitev pri prikazu prijateljev prijateljev določenega uporabnika, ko je povprečno število prijateljev 500.
  • Zakasnitev pri pridobivanju 100 najboljših vnosov iz uporabnikove zgodovine, ko uporabnik sledi 500 drugim uporabnikom z X vnosi na uro.

Vrednotenje in eksperimentiranje lahko vključujeta takšne kritične primere, dokler niste prepričani, da zbirka podatkov izpolnjuje zahteve glede zmogljivosti. Podobno pravilo palca upošteva tudi to razčlenitev pri zbiranju meritev zakasnitve in določanju SLO.

Pri zbiranju metrik za vsako operacijo bodite pozorni na visoko kardinalnost. Uporabite dnevnike, zbiranje dogodkov ali porazdeljeno sledenje, da pridobite zmogljive podatke za odpravljanje napak. V članku "Želite odpraviti napake v zakasnitvi?» se lahko seznanite z metodologijami za odpravljanje napak.

Ugnezdene transakcije so lahko nevarne

Vsak DBMS ne podpira ugnezdenih transakcij, a ko jih podpirajo, lahko takšne transakcije povzročijo nepričakovane napake, ki jih ni vedno lahko odkriti (to pomeni, da mora biti očitno, da obstaja nekakšna anomalija).

Uporabi ugnezdenih transakcij se lahko izognete z odjemalskimi knjižnicami, ki jih lahko zaznajo in obidejo. Če ugnezdenih transakcij ni mogoče opustiti, bodite še posebej previdni pri njihovem izvajanju, da se izognete nepričakovanim situacijam, ko so dokončane transakcije pomotoma prekinjene zaradi ugnezdenih.

Enkapsulacija transakcij v različne plasti lahko privede do nepričakovanih ugnezdenih transakcij, z vidika berljivosti kode pa lahko oteži razumevanje avtorjevih namenov. Oglejte si naslednji program:

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

Kakšen bo rezultat zgornje kode? Ali bo povrnil obe transakciji ali samo notranjo? Kaj se zgodi, če se zanašamo na več plasti knjižnic, ki zajemajo ustvarjanje transakcij za nas? Bomo znali prepoznati in izboljšati takšne primere?

Predstavljajte si podatkovno plast z več operacijami (npr. newAccount) je že implementiran v lastne transakcije. Kaj se zgodi, če jih zaženete kot del poslovne logike na višji ravni, ki teče znotraj lastne transakcije? Kakšna bi bila izolacija in doslednost v tem primeru?

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

Namesto iskanja odgovorov na tako neskončna vprašanja se je bolje izogniti ugnezdenim transakcijam. Navsezadnje lahko vaša podatkovna plast zlahka izvaja operacije na visoki ravni, ne da bi ustvarila lastne transakcije. Poleg tega je poslovna logika sama sposobna iniciirati transakcijo, izvajati operacije na njej, izvršiti ali prekiniti transakcijo.

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.

Transakcije ne smejo biti vezane na stanje aplikacije

Včasih je mamljivo uporabiti stanje aplikacije v transakcijah za spreminjanje določenih vrednosti ali prilagajanje parametrov poizvedbe. Ključni odtenek, ki ga je treba upoštevati, je pravilen obseg uporabe. Odjemalci pogosto znova zaženejo transakcije, ko pride do težav z omrežjem. Če je transakcija nato odvisna od stanja, ki ga spreminja nek drug proces, lahko izbere napačno vrednost glede na možnost podatkovne tekme. Transakcije morajo upoštevati tveganje podatkovne tekme v aplikaciji.

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

Zgornja transakcija bo povečala zaporedno številko vsakič, ko bo izvedena, ne glede na končni rezultat. Če potrditev ne uspe zaradi težav z omrežjem, bo zahteva ob ponovnem poskusu izvedena z drugo zaporedno številko.

Načrtovalci poizvedb vam lahko povedo veliko o bazi podatkov

Načrtovalci poizvedb določijo, kako bo poizvedba izvedena v bazi podatkov. Prav tako analizirajo zahteve in jih optimizirajo, preden jih pošljejo. Načrtovalci lahko podajo le nekatere možne ocene na podlagi signalov, s katerimi razpolagajo. Na primer, kateri je najboljši način iskanja za naslednjo poizvedbo?

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

Rezultate je mogoče pridobiti na dva načina:

  • Pregled celotne tabele: Ogledate si lahko vsak vnos v tabeli in vrnete članke z ujemajočim se imenom avtorja ter jih nato razvrstite.
  • Pregled indeksa: Z indeksom lahko poiščete ujemajoče se ID-je, pridobite te vrstice in jih nato razporedite.

Naloga načrtovalca poizvedb je ugotoviti, katera strategija je najboljša. Upoštevati je treba, da imajo načrtovalci poizvedb le omejene zmožnosti predvidevanja. To lahko vodi do slabih odločitev. DBA ali razvijalci jih lahko uporabijo za diagnosticiranje in natančno nastavitev neučinkovitih poizvedb. Nove različice DBMS lahko konfigurirajo načrtovalce poizvedb, samodiagnoza pa lahko pomaga pri posodabljanju baze podatkov, če nova različica povzroči težave z zmogljivostjo. Počasni dnevniki poizvedb, poročila o težavah z zakasnitvami ali statistični podatki o času izvajanja lahko pomagajo prepoznati poizvedbe, ki potrebujejo optimizacijo.

Nekatere metrike, ki jih predstavi načrtovalec poizvedb, so lahko podvržene šumu (zlasti pri ocenjevanju zakasnitve ali časa procesorja). Dober dodatek k planerjem so orodja za sledenje in sledenje poti izvajanja. Omogočajo vam diagnosticiranje takšnih težav (žal, vsi DBMS-ji ne nudijo takšnih orodij).

Spletna migracija je težka, a mogoča

Spletna selitev, selitev v živo ali selitev v realnem času pomeni selitev iz ene baze podatkov v drugo brez izpadov ali poškodb podatkov. Selitev v živo je lažje izvesti, če prehod poteka znotraj istega DBMS/motorja. Situacija postane bolj zapletena, ko se je treba premakniti na nov DBMS z drugačnimi zahtevami glede zmogljivosti in sheme.

Obstajajo različni modeli spletne migracije. Tukaj je eden od njih:

  • Omogočite dvojni vnos v obe bazi podatkov. Nova baza podatkov v tej fazi nima vseh podatkov, ampak sprejema le najnovejše podatke. Ko ste o tem prepričani, lahko nadaljujete na naslednji korak.
  • Omogoči branje iz obeh zbirk podatkov.
  • Konfigurirajte sistem tako, da se branje in pisanje izvajata predvsem v novi bazi podatkov.
  • Prenehajte pisati v staro zbirko podatkov, hkrati pa nadaljujte z branjem podatkov iz nje. Na tej stopnji je v novi bazi podatkov še vedno nekaj podatkov. Prepisati jih je treba iz stare baze podatkov.
  • Stara zbirka podatkov je samo za branje. Kopirajte manjkajoče podatke iz stare baze podatkov v novo. Po končani selitvi zamenjajte poti do nove baze podatkov, staro pa zaustavite in jo izbrišite iz sistema.

Za dodatne informacije priporočam kontakt članek, ki podrobno opisuje migracijsko strategijo Stripe, ki temelji na tem modelu.

Znatno povečanje baze podatkov pomeni povečanje nepredvidljivosti

Rast baze podatkov vodi do nepredvidljivih težav, povezanih z njenim obsegom. Več ko vemo o notranji strukturi baze podatkov, bolje lahko predvidimo, kako se bo merila. Nekatere trenutke pa je vseeno nemogoče predvideti.
Ko se baza povečuje, lahko prejšnje predpostavke in pričakovanja glede količine podatkov in zahtev glede pasovne širine omrežja postanejo zastareli. Takrat se pojavi vprašanje večjih prenov oblikovanja, obsežnih operativnih izboljšav, ponovnega premisleka o uvajanju ali selitvi na druge DBMS, da bi se izognili morebitnim težavam.

A ne mislite, da je potrebno le odlično poznavanje notranje strukture obstoječe baze podatkov. Nove lestvice bodo s seboj prinesle nove neznanke. Nepredvidljive težave, neenakomerna porazdelitev podatkov, nepričakovane težave s pasovno širino in strojno opremo, vedno večji promet in novi segmenti omrežja vas bodo prisilili, da ponovno razmislite o svojem pristopu k zbirki podatkov, podatkovnem modelu, modelu uvajanja in velikosti baze podatkov.

...

V času, ko sem začel razmišljati o objavi tega članka, je bilo na mojem prvotnem seznamu že pet več stvari. Potem je prišlo ogromno število nove ideje o tem, kaj je še mogoče pokriti. Zato se članek dotika najmanj očitnih problemov, ki zahtevajo maksimalno pozornost. Vendar to ne pomeni, da je tema izčrpana in se k njej ne bom več vračal v svojih prihodnjih gradivih in ne bom spreminjal trenutnega.

PS

Preberite tudi na našem blogu:

Vir: www.habr.com

Dodaj komentar