Pli da programistoj devus scii ĉi tion pri datumbazoj

Notu. transl.: Jaana Dogan estas sperta inĝeniero ĉe Guglo kiu nuntempe laboras pri observeblo de la produktadservoj de la firmao skribitaj en Go. En ĉi tiu artikolo, kiu akiris grandan popularecon inter la anglalingva publiko, ŝi kolektis en 17 poentoj gravajn teknikajn detalojn pri DBMS-oj (kaj foje distribuitaj sistemoj ĝenerale), kiuj estas utile konsideri por programistoj de grandaj/postulemaj aplikaĵoj.

Pli da programistoj devus scii ĉi tion pri datumbazoj

La granda plimulto de komputilaj sistemoj konservas sian staton kaj, sekve, postulas iun specon de datumstokado. Mi akumulis scion pri datumbazoj dum longa tempo, survoje farante projektajn erarojn, kiuj kaŭzis datumajn perdojn kaj malfunkciojn. En sistemoj kiuj prilaboras grandajn volumojn de informoj, datumbazoj kuŝas ĉe la koro de la sistema arkitekturo kaj funkcias kiel ŝlosila elemento en elektado de la optimuma solvo. Malgraŭ la fakto, ke oni atentas la laboron de la datumbazo, la problemoj, kiujn aplikaĵprogramistoj provas antaŭvidi, ofte estas nur la pinto de la glacimonto. En ĉi tiu serio de artikoloj, mi dividas kelkajn ideojn, kiuj estos utilaj por programistoj, kiuj ne estas specialigitaj en ĉi tiu kampo.

  1. Vi bonŝancas se 99,999% de la tempo la reto ne kaŭzas problemojn.
  2. ACIDO signifas multajn malsamajn aferojn.
  3. Ĉiu datumbazo havas siajn proprajn mekanismojn por certigi konsistencon kaj izolitecon.
  4. Optimisma blokado venas al la savo kiam estas malfacile konservi la kutiman.
  5. Estas aliaj anomalioj krom malpuraj legaĵoj kaj perdo de datumoj.
  6. La datumbazo kaj la uzanto ne ĉiam konsentas pri la agado.
  7. Apliknivela sharding povas esti movita ekster la aplikaĵo.
  8. Aŭtomata pliigo povas esti danĝera.
  9. Malfreŝaj datumoj povas esti utilaj kaj ne bezonas esti ŝlositaj.
  10. Misprezentoj estas tipaj por iuj tempofontoj.
  11. Prokrasto havas multajn signifojn.
  12. Efikecpostuloj devas esti taksitaj por specifa transakcio.
  13. Nestitaj transakcioj povas esti danĝeraj.
  14. Transakcioj ne estu ligitaj al aplika stato.
  15. Demandaj planistoj povas diri al vi multon pri datumbazoj.
  16. Reta migrado estas malfacila, sed ebla.
  17. Signifa pliiĝo en la datumbazo kunportas pliiĝon de neantaŭvidebleco.

Mi ŝatus danki Emmanuel Odeke, Rein Henrichs kaj aliajn pro iliaj komentoj pri pli frua versio de ĉi tiu artikolo.

Vi bonŝancas se 99,999% de la tempo la reto ne kaŭzas problemojn.

Restas la demando pri kiom fidindaj estas modernaj retaj teknologioj kaj kiom ofte sistemoj malfunkcias pro retaj fiaskoj. Informoj pri ĉi tiu afero estas malabundaj kaj esplorado ofte estas dominata de grandaj organizoj kun specialigitaj retoj, ekipaĵoj kaj dungitaro.

Kun havebleca indico de 99,999% por Spanner (la tutmonde distribuita datumbazo de Guglo), Guglo asertas, ke nur 7,6% problemoj rilatas al la reto. Samtempe, la kompanio nomas sian specialigitan reton la "ĉefa kolono" de alta havebleco. Studu Bailis kaj Kingsbury, farita en 2014, defias unu el la "miskomprenoj pri distribuita komputado", kiun Peter Deutsch formulis en 1994. Ĉu la reto vere estas fidinda?

Ampleksa esplorado ekster gigantaj kompanioj, farita por la pli larĝa Interreto, simple ne ekzistas. Ankaŭ ne ekzistas sufiĉe da datumoj de la ĉefaj ludantoj pri kia procento de la problemoj de siaj klientoj rilatas al reto. Ni bone scias pri malfunkcioj en la reto de grandaj nubaj provizantoj, kiuj povas forigi tutan parton de la Interreto dum kelkaj horoj simple ĉar ili estas altprofilaj eventoj, kiuj influas grandan nombron da homoj kaj kompanioj. Retaj malfunkcioj povas kaŭzi problemojn en multaj pli da kazoj, eĉ se ne ĉiuj tiuj kazoj estas en la spoto. Klientoj de nubaj servoj ankaŭ ne scias ion pri la kaŭzoj de problemoj. Se estas malsukceso, estas preskaŭ neeble atribui ĝin al reta eraro flanke de la servoprovizanto. Por ili, triaj servoj estas nigraj skatoloj. Estas neeble taksi la efikon sen esti granda provizanto de servoj.

Konsiderante kion la grandaj ludantoj raportas pri siaj sistemoj, estas sekure diri, ke vi bonŝancas, se retaj malfacilaĵoj respondecas nur pri malgranda procento de eblaj malfunkciaj problemoj. Retaj komunikadoj ankoraŭ suferas pro tiaj sekularaj aferoj kiel aparataj misfunkciadoj, topologioŝanĝoj, administraj agordaj ŝanĝoj kaj elektropaneoj. Lastatempe mi surpriziĝis eksciante, ke la listo de eblaj problemoj estis aldonita mordoj de ŝarko (jes, vi bone aŭdis).

ACIDO signifas multajn malsamajn aferojn

La akronimo ACID signifas Atomicity, Consistency, Isolation, Reliability. Ĉi tiuj propraĵoj de transakcioj celas certigi ilian validecon en la okazo de misfunkciadoj, eraroj, aparataj misfunkciadoj ktp. Sen ACID aŭ similaj skemoj, estus malfacile por aplikaĵprogramistoj diferenci inter kio ili respondecas pri kaj pri kio respondecas la datumbazo. La plej multaj interrilataj transakciaj datumbazoj provas esti ACID-observemaj, sed novaj aliroj kiel NoSQL kaŭzis multajn datumbazojn sen ACID-transakcioj ĉar ili estas multekostaj por efektivigi.

Kiam mi unue eniris la industrion, nia teknika gvidanto parolis pri kiom grava estis la ACID-koncepto. Por esti justa, ACID estas konsiderita malglata priskribo prefere ol strikta efektivignormo. Hodiaŭ mi trovas ĝin plejparte utila ĉar ĝi levas specifan kategorion da problemoj (kaj sugestas gamon da eblaj solvoj).

Ne ĉiu DBMS estas ACID konforma; En la sama tempo, datumbazaj efektivigoj kiuj subtenas ACID komprenas la aron de postuloj alimaniere. Unu el la kialoj kial ACID-efektivigoj estas neregulaj ŝuldiĝas al la multaj kompromisoj kiuj devas esti faritaj por efektivigi ACID-postulojn. Kreintoj povas prezenti siajn datumbazojn kiel ACID-konformajn, sed la interpreto de randkazoj povas varii draste, same kiel la mekanismo por pritrakti "neprobablajn" okazaĵojn. Almenaŭ, programistoj povas akiri altnivelan komprenon pri la komplikaĵoj de bazaj efektivigoj por akiri taŭgan komprenon pri sia speciala konduto kaj projektaj kompromisoj.

La debato pri ĉu MongoDB konformas al ACID-postuloj daŭras eĉ post la publikigo de versio 4. MongoDB ne estas subtenata delonge arbohakado, kvankam defaŭlte datumoj estis faritaj al disko ne pli ol unufoje ĉiujn 60 sekundojn. Imagu la sekvan scenaron: aplikaĵo afiŝas du skribaĵojn (w1 kaj w2). MongoDB sukcese stokas w1, sed w2 estas perdita pro aparatara fiasko.

Pli da programistoj devus scii ĉi tion pri datumbazoj
Diagramo ilustranta la scenaron. MongoDB kraŝas antaŭ ol ĝi povas skribi datumojn al disko

Engaĝiĝi al disko estas multekosta procezo. Evitante oftajn komitojn, programistoj plibonigas registran rendimenton koste de fidindeco. MongoDB nuntempe subtenas registradon, sed malpuraj skribaĵoj ankoraŭ povas influi datuman integrecon ĉar protokoloj estas kaptitaj ĉiujn 100ms defaŭlte. Tio estas, simila scenaro ankoraŭ eblas por ŝtipoj kaj la ŝanĝoj prezentitaj en ili, kvankam la risko estas multe pli malalta.

Ĉiu datumbazo havas sian propran konsistencon kaj izolaj mekanismoj

El la ACID-postuloj, konsistenco kaj izoliteco fanfaronas pri la plej granda nombro da malsamaj efektivigoj ĉar la gamo de kompromisoj estas pli larĝa. Oni devas diri, ke konsistenco kaj izolado estas sufiĉe multekostaj funkcioj. Ili postulas kunordigon kaj pliigas konkuradon pri datuma konsistenco. La komplekseco de la problemo pliiĝas signife kiam estas necese grimpi la datumbazon horizontale tra multoblaj datumcentroj (precipe se ili situas en malsamaj geografiaj regionoj). Atingi altan nivelon de konsistenco estas tre malfacila, ĉar ĝi ankaŭ reduktas haveblecon kaj pliigas retsegmentadon. Por pli ĝenerala klarigo de ĉi tiu fenomeno, mi konsilas vin aludi CAP-teoremo. Estas ankaŭ notinde, ke aplikaĵoj povas trakti malgrandajn kvantojn da nekongrueco, kaj programistoj povas kompreni la nuancojn de la problemo sufiĉe bone por efektivigi plian logikon en la aplikaĵo por trakti nekonsekvencojn sen multe fidi la datumbazon por trakti ĝin.

DBMSoj ofte disponigas malsamajn nivelojn de izoliteco. Programistoj de aplikaĵoj povas elekti la plej efikan laŭ siaj preferoj. Malalta izolado permesas pliigi rapidecon, sed ankaŭ pliigas la riskon de datumvetkuro. Alta izolado reduktas ĉi tiun probablecon, sed malrapidigas laboron kaj povas konduki al konkuro, kio kondukos al tiaj bremsoj en la bazo, ke komenciĝas misfunkciadoj.

Pli da programistoj devus scii ĉi tion pri datumbazoj
Revizio de ekzistantaj samtempaj modeloj kaj rilatoj inter ili

La SQL-normo difinas nur kvar izolaj niveloj, kvankam en teorio kaj praktiko estas multaj pli. Jepson.io ofertas bonegan superrigardon de ekzistantaj samtempaj modeloj. Ekzemple, Google Spanner garantias eksteran seriigeblon kun horloĝsinkronigo, kaj kvankam tio estas pli strikta izoleca tavolo, ĝi ne estas difinita en normaj izolaj tavoloj.

La SQL-normo mencias la sekvajn izoligajn nivelojn:

  • Serializebla (plej strikta kaj multekosta): Serializa ekzekuto havas la saman efikon kiel iu sinsekva transakcio-ekzekuto. Sinsekva ekzekuto signifas, ke ĉiu posta transakcio komenciĝas nur post kiam la antaŭa estas kompletigita. Oni devas rimarki, ke la nivelo Serializebla ofte efektivigite kiel tielnomita momentfotoizolado (ekzemple, en Orakolo) pro diferencoj en interpreto, kvankam momentfotoizolado mem ne estas reprezentita en la SQL-normo.
  • Ripeteblaj legaĵoj: Neengaĝitaj rekordoj en la nuna transakcio estas haveblaj al la nuna transakcio, sed ŝanĝoj faritaj de aliaj transakcioj (kiel novaj vicoj) ne videbla.
  • Legu kompromitita: Neengaĝitaj datumoj ne disponeblas por transakcioj. En ĉi tiu kazo, transakcioj povas nur vidi faritajn datumojn, kaj fantomaj legadoj povas okazi. Se transakcio enigas kaj transigas novajn vicojn, la nuna transakcio povos vidi ilin kiam demandite.
  • Legu neengaĝite (malplej strikta kaj multekosta nivelo): Malpuraj legoj estas permesitaj, transakcioj povas vidi neengaĝitajn ŝanĝojn faritajn de aliaj transakcioj. En praktiko, ĉi tiu nivelo povas esti utila por malglataj taksoj, kiel demandoj COUNT(*) sur la tablo.

nivelo Serializebla minimumigas la riskon de datumvetkuroj, estante la plej multekosta por efektivigi kaj rezultigante la plej altan konkurencivan ŝarĝon sur la sistemo. Aliaj izolaj niveloj estas pli facile efektivigeblaj, sed pliigas la verŝajnecon de datumvetkuroj. Iuj DBMS-oj permesas al vi agordi laŭmendan izolitecon, aliaj havas fortajn preferojn kaj ne ĉiuj niveloj estas subtenataj.

Subteno por izolaj niveloj ofte estas reklamita en antaŭfiksita DBMS, sed nur zorgema studo de ĝia konduto povas malkaŝi kio efektive okazas.

Pli da programistoj devus scii ĉi tion pri datumbazoj
Revizio de samtempaj anomalioj sur malsamaj izolaj niveloj por malsamaj DBMSoj

Martin Kleppmann en sia projekto ermitejo Kompparas malsamajn izoligajn nivelojn, parolas pri samtempaj anomalioj, kaj ĉu la datumbazo kapablas aliĝi al aparta izoliteca nivelo. La esplorado de Kleppmann montras kiom malsame datumbazaj programistoj pensas pri izolaj niveloj.

Optimisma blokado venas al la savo kiam estas malfacile konservi la kutiman.

Blokado povas esti tre multekosta, ne nur ĉar ĝi pliigas konkuradon en la datumbazo, sed ankaŭ ĉar ĝi postulas, ke la aplikaĵoserviloj konstante konektiĝu al la datumbazo. Retsegmentado povas pliseverigi ekskluzivajn ŝlosajn situaciojn kaj konduki al blokiĝo, kiuj malfacilas identigi kaj solvi. En kazoj kie ekskluziva ŝlosado ne taŭgas, optimisma ŝlosado helpas.

Optimisma seruro estas metodo en kiu dum legado de ĉeno, ĝi konsideras ĝian version, ĉeksumon aŭ tempon de lasta modifo. Ĉi tio ebligas al vi certigi, ke ne ekzistas atoma versio-ŝanĝo antaŭ ol ŝanĝi eniron:

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

En ĉi tiu kazo, ĝisdatigi la tabelon products ne estos efektivigita se alia operacio antaŭe faris ŝanĝojn al ĉi tiu vico. Se neniuj aliaj operacioj estis faritaj sur ĉi tiu vico, la ŝanĝo por unu vico okazos kaj ni povas diri, ke la ĝisdatigo sukcesis.

Estas aliaj anomalioj krom malpuraj legaĵoj kaj perdo de datumoj

Kiam temas pri datumkonsistenco, la fokuso estas sur la potencialo por raskondiĉoj, kiuj povas konduki al malpuraj legaĵoj kaj datumperdo. Tamen, datumaj anomalioj ne ĉesas tie.

Unu ekzemplo de tiaj anomalioj estas registra misprezento (skribi misformojn). Distordoj estas malfacile detekteblaj ĉar ili ne estas kutime aktive serĉitaj. Ili ne ŝuldiĝas al malpuraj legaĵoj aŭ al perdo de datumoj, sed al malobservoj de logikaj limoj metitaj sur la datumoj.

Ekzemple, ni konsideru monitoran aplikaĵon, kiu postulas, ke unu telefonisto estu ĉiam atenta:

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;

En la supra situacio, rekorda korupto okazos se ambaŭ transakcioj estas sukcese faritaj. Kvankam ne estis malpuraj legaĵoj aŭ perdo de datumoj, la integreco de la datumoj estis endanĝerigita: nun du homoj estas konsiderataj samtempe survokaj.

Seriigebla izoliteco, skemdezajno aŭ datumbazaj limoj povas helpi elimini skribkorupton. Programistoj devas povi identigi tiajn anomaliojn dum evoluo por eviti ilin en produktado. Samtempe, registraj misprezentoj estas ege malfacile serĉeblaj en la kodbazo. Precipe en grandaj sistemoj, kiam malsamaj evoluigaj teamoj respondecas pri efektivigado de funkcioj bazitaj sur la samaj tabeloj kaj ne konsentas pri la specifaĵoj de datuma aliro.

La datumbazo kaj la uzanto ne ĉiam konsentas pri tio, kion fari

Unu el la ĉefaj trajtoj de datumbazoj estas la garantio de ekzekut-ordo, sed ĉi tiu ordo mem eble ne travideblas al la programisto. Datumbazoj efektivigas transakciojn en la ordo en kiu ili estas ricevitaj, ne en la ordo kiun programistoj intencas. La ordo de transakcioj malfacilas antaŭdiri, precipe en tre ŝarĝitaj paralelaj sistemoj.

Dum evoluo, precipe kiam oni laboras kun ne-blokaj bibliotekoj, malbona stilo kaj malalta legebleco povas igi uzantojn kredi, ke transakcioj estas sinsekve efektivigitaj, kiam fakte ili povus alveni en la datumbazon en ajna ordo.

Unuavide, en la suba programo, T1 kaj T2 estas nomitaj sinsekve, sed se ĉi tiuj funkcioj estas neblokaj kaj tuj redonas la rezulton en la formo promesi, tiam la ordo de vokoj estos determinita de la momentoj, kiam ili eniris la datumbazon:

rezulto1 = T1() // realaj rezultoj estas promesoj
rezulto2 = T2()

Se atomeco estas postulata (t.e., aŭ ĉiuj operacioj devas esti kompletigitaj aŭ interrompitaj) kaj sekvenco gravas, tiam operacioj T1 kaj T2 devas esti faritaj ene de ununura transakcio.

Apliknivela sharding povas esti movita ekster la aplikaĵo

Sharding estas metodo por horizontale dispartigi datumbazon. Iuj datumbazoj povas aŭtomate disigi datumojn horizontale, dum aliaj ne povas aŭ ne tre lertas pri ĝi. Kiam datumoj-arkitektoj/programistoj povas antaŭdiri precize kiel datumoj estos aliritaj, ili povas krei horizontalajn sekciojn en uzantspaco anstataŭ delegi ĉi tiun laboron al la datumbazo. Ĉi tiu procezo nomiĝas "apliknivela sharding" (apliknivela dividado).

Bedaŭrinde, ĉi tiu nomo ofte kreas la miskomprenon, ke sharding vivas en aplikaĵservoj. Fakte, ĝi povas esti efektivigita kiel aparta tavolo antaŭ la datumbazo. Depende de datenkresko kaj skemripetoj, shardingpostuloj povas iĝi sufiĉe kompleksaj. Iuj strategioj povas profiti el la kapablo ripeti sen devi redeploji aplikaĵservilojn.

Pli da programistoj devus scii ĉi tion pri datumbazoj
Ekzemplo de arkitekturo en kiu aplikaĵserviloj estas apartigitaj de la sharding-servo

Movi sharding en apartan servon vastigas la kapablon uzi malsamajn sharding strategioj sen la bezono redeploji aplikojn. Vitess estas ekzemplo de tia sharding-sistemo ĉe la aplikaĵnivelo. Vitess disponigas horizontalan sharding por MySQL kaj permesas klientojn konekti al ĝi per la MySQL-protokolo. La sistemo segmentas la datumojn en malsamajn MySQL-nodojn, kiuj scias nenion pri unu la alian.

Aŭtomata pliigo povas esti danĝera

AUTOINCREMENT estas ofta maniero generi primarajn ŝlosilojn. Estas ofte kazoj kiam datumbazoj estas utiligitaj kiel ID-generatoroj, kaj la datumbazo enhavas tabelojn dizajnitajn por generi identigilojn. Estas pluraj kialoj, kial generi primarajn ŝlosilojn per aŭtomata pliigo estas malproksima de ideala:

  • En distribuita datumbazo, aŭtomata pliigo estas grava problemo. Por generi la ID, tutmonda seruro estas postulata. Anstataŭe, vi povas generi UUID: ĉi tio ne postulas interagadon inter malsamaj datumbazaj nodoj. Aŭtomata pliigo per seruroj povas konduki al disputo kaj signife redukti rendimenton sur enmetoj en distribuitaj situacioj. Kelkaj DBMSoj (ekzemple, MySQL) povas postuli specialan agordon kaj pli zorgeman atenton por konvene organizi majstran-majstran reproduktadon. Kaj estas facile fari erarojn dum agordado, kio kondukos al registrado-malsukcesoj.
  • Kelkaj datumbazoj havas dispartigajn algoritmojn bazitajn sur primaraj ŝlosiloj. Sinsekvaj identigiloj povas konduki al neantaŭvideblaj varmaj punktoj kaj pliigita ŝarĝo sur iuj sekcioj dum aliaj restas neaktivaj.
  • Primara ŝlosilo estas la plej rapida maniero por aliri vicon en datumbazo. Kun pli bonaj manieroj identigi rekordojn, sinsekvaj identigiloj povas igi la plej gravan kolumnon en tabeloj en senutilan kolumnon plenigitan de sensignifaj valoroj. Tial, kiam ajn eblas, bonvolu elekti tutmonde unikan kaj naturan ĉefan ŝlosilon (ekz. uzantnomo).

Antaŭ ol decidi pri aliro, konsideru la efikon de aŭtomate pliigaj ID-oj kaj UUID-oj sur indeksado, dispartigo kaj sharding.

Malfreŝaj datumoj povas esti utilaj kaj ne postulas ŝlosadon

Multiversion Concurrency Control (MVCC) efektivigas multajn el la konsekvencaj postuloj, kiuj estis mallonge diskutitaj supre. Iuj datumbazoj (ekzemple Postgres, Spanner) uzas MVCC por "nutri" transakciojn per momentfotoj - pli malnovaj versioj de la datumbazo. Momentfototransakcioj ankaŭ povas esti seriigitaj por certigi konsistencon. Dum legado de malnova momentfoto, malaktualaj datumoj estas legitaj.

Legi iomete malnoviĝintajn datumojn povas esti utila, ekzemple, kiam oni generas analizojn el la datumoj aŭ kalkulas proksimumajn totalajn valorojn.

La unua avantaĝo labori kun heredaj datumoj estas malalta latencia (precipe se la datumbazo estas distribuita tra malsamaj geografioj). La dua estas, ke nurlegeblaj transakcioj estas senŝlosaj. Ĉi tio estas grava avantaĝo por aplikoj, kiuj legas multe, kondiĉe ke ili povas pritrakti malnoviĝintajn datumojn.

Pli da programistoj devus scii ĉi tion pri datumbazoj
La aplikaĵo-servilo legas datumojn de la loka kopio, kiu estas 5 sekundoj malaktuala, eĉ se la plej nova versio estas havebla ĉe la alia flanko de la Pacifiko.

DBMS-oj aŭtomate purigas pli malnovajn versiojn kaj, en iuj kazoj, permesas al vi fari tion laŭpeto. Ekzemple, Postgres permesas al uzantoj fari VACUUM laŭpeto, kaj ankaŭ periode plenumas ĉi tiun operacion aŭtomate. Spanner prizorgas rubkolektiston por forigi momentfotojn pli malnovajn ol unu horon.

Ĉiufoje fontoj estas submetataj al misprezento

La plej bone konservita sekreto en komputiko estas, ke ĉiuj tempaj API-oj mensogas. Fakte, niaj maŝinoj ne scias la precizan nunan tempon. Komputiloj enhavas kvarckristalojn kiuj generas vibrojn kiuj estas uzataj por konservi tempon. Tamen, ili ne estas sufiĉe precizaj kaj eble estas antaŭ/malfruas la precizan tempon. La ŝanĝo povas atingi 20 sekundojn tage. Tial la tempo en niaj komputiloj devas esti periode sinkronigita kun la reto.

NTP-serviloj estas uzataj por sinkronigado, sed la sinkroniga procezo mem estas kondiĉigita de retaj prokrastoj. Eĉ sinkronigi kun NTP-servilo en la sama datumcentro prenas iom da tempo. Estas klare, ke labori kun publika NTP-servilo povas konduki al eĉ pli granda misprezento.

Atomaj horloĝoj kaj iliaj GPS-ekvivalentoj estas pli bonaj por determini la nunan horon, sed ili estas multekostaj kaj postulas kompleksan aranĝon, do ili ne povas esti instalitaj sur ĉiu aŭto. Pro tio, datumcentroj uzas nivelan aliron. Atomaj kaj/aŭ GPS-horloĝoj montras la precizan tempon, post kiu ĝi estas elsendita al aliaj maŝinoj per malĉefaj serviloj. Ĉi tio signifas, ke ĉiu maŝino spertos certan ofseton de la ĝusta tempo.

La situacio estas pligravigita de la fakto, ke aplikaĵoj kaj datumbazoj ofte troviĝas sur malsamaj maŝinoj (se ne en malsamaj datumcentroj). Tiel, la tempo diferencos ne nur sur DB-nodoj distribuitaj tra malsamaj maŝinoj. Ĝi ankaŭ estos malsama sur la aplikaĵoservilo.

Google TrueTime prenas tute alian aliron. Plej multaj homoj kredas, ke la progreso de Guglo en ĉi tiu direkto estas klarigita per la banala transiro al atomaj kaj GPS-horloĝoj, sed ĉi tio estas nur parto de la granda bildo. Jen kiel funkcias TrueTime:

  • TrueTime uzas du malsamajn fontojn: GPS kaj atomhorloĝoj. Tiuj horloĝoj havas ne-korelaciajn fiaskoreĝimojn. [vidu paĝon 5 por detaloj tie - ĉ. traduk.), do ilia komuna uzo pliigas fidindecon.
  • TrueTime havas nekutiman API. Ĝi resendas tempon kiel intervalon kun mezuraro kaj necerteco enkonstruitaj en ĝi. La reala momento en tempo estas ie inter la supraj kaj malsupraj limoj de la intervalo. Spanner, la distribuita datumbazo de Guglo, simple atendas ĝis estas sekure diri ke la nuna tempo estas ekster intervalo. Ĉi tiu metodo enkondukas iom da latenteco en la sistemon, precipe se la necerteco sur la majstroj estas alta, sed certigas ĝustecon eĉ en tutmonde distribuita situacio.

Pli da programistoj devus scii ĉi tion pri datumbazoj
La Spanner-komponentoj uzas TrueTime, kie TT.now() resendas intervalon, do la Spanner simple dormas ĝis la punkto, kie ĝi povas esti certa, ke la nuna tempo pasis certan punkton.

Reduktita precizeco en determini la nunan tempon signifas pliiĝon en la daŭro de Spanner-operacioj kaj malkreskon en rendimento. Tial gravas konservi la plej altan eblan precizecon kvankam estas neeble akiri tute precizan horloĝon.

Prokrasto havas multajn signifojn

Se vi demandas dekduon da fakuloj pri kio estas prokrasto, vi verŝajne ricevos malsamajn respondojn. En DBMS latencia estas ofte nomita "datumbaza latenco" kaj estas diferenca de kio estas perceptita fare de la kliento. La fakto estas, ke la kliento observas la sumon de la reta prokrasto kaj la datumbaza prokrasto. La kapablo izoli la tipon de latenteco estas kritika dum elpurigado de kreskantaj problemoj. Dum kolektado kaj montrado de metrikoj, ĉiam provu observi ambaŭ tipojn.

Efikecpostuloj devas esti taksitaj por specifa transakcio

Foje la agado-karakterizaĵoj de DBMS kaj ĝiaj limigoj estas specifitaj laŭ skriba/lega trairo kaj latenteco. Ĉi tio disponigas ĝeneralan superrigardon de ŝlosilaj sistemaj parametroj, sed kiam oni taksas la agadon de nova DBMS, multe pli ampleksa aliro estas aparte taksi kritikajn operaciojn (por ĉiu demando kaj/aŭ transakcio). Ekzemploj:

  • Skribu trafluon kaj latentecon kiam enmetas novan vicon en tabelon X (kun 50 milionoj da vicoj) kun specifitaj limoj kaj vicoplenigo en rilataj tabeloj.
  • Prokrasto en montri amikojn de amikoj de certa uzanto kiam la averaĝa nombro da amikoj estas 500.
  • Latenteco en prenado de la supraj 100 enskriboj de la historio de uzanto kiam la uzanto sekvas 500 aliajn uzantojn kun X enskriboj je horo.

Taksado kaj eksperimentado povas inkluzivi tiajn kritikajn kazojn ĝis vi certas, ke la datumbazo plenumas la agadon-postulojn. Simila regulo ankaŭ enkalkulas ĉi tiun disrompon dum kolektado de latenciaj metrikoj kaj determinas SLOojn.

Estu konscia pri alta kardinaleco dum kolektado de metrikoj por ĉiu operacio. Uzu protokolojn, kolekton de eventoj aŭ distribuitajn spurojn por akiri alt-potencajn sencimigajn datumojn. En la artikolo "Ĉu vi volas Sencimigi Latentecon?» vi povas konatiĝi kun metodologioj de prokrasta sencimigo.

Nestitaj transakcioj povas esti danĝeraj

Ne ĉiu DBMS subtenas nestitajn transakciojn, sed kiam ili faras, tiaj transakcioj povas rezultigi neatenditajn erarojn, kiuj ne ĉiam estas facile detekteblaj (tio estas, devus esti evidente, ke ekzistas ia anomalio).

Vi povas eviti uzi nestitajn transakciojn uzante klientajn bibliotekojn, kiuj povas detekti kaj preteriri ilin. Se nestitaj transakcioj ne povas esti forlasitaj, zorgu speciale pri ilia efektivigo por eviti neatenditajn situaciojn, kie finitaj transakcioj estas hazarde interrompitaj pro nestitaj.

Enkapsuligi transakciojn en malsamaj tavoloj povas konduki al neatenditaj nestitaj transakcioj, kaj de koda legebla vidpunkto, ĝi povas malfaciligi kompreni la intencojn de la aŭtoro. Rigardu la sekvan programon:

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

Kio estos la eligo de la supra kodo? Ĉu ĝi retroigos ambaŭ transakciojn, aŭ nur la internan? Kio okazas se ni dependas de multoblaj tavoloj de bibliotekoj, kiuj enkapsuligas la kreadon de transakcioj por ni? Ĉu ni povos identigi kaj plibonigi tiajn kazojn?

Imagu datumtavolon kun multoblaj operacioj (ekz. newAccount) jam estas efektivigita en siaj propraj transakcioj. Kio okazas se vi kuras ilin kiel parto de pli alta nivela komerca logiko kiu funkcias ene de sia propra transakcio? Kio estus la izolado kaj konsistenco en ĉi tiu kazo?

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

Anstataŭ serĉi respondojn al tiaj senfinaj demandoj, estas pli bone eviti nestitajn transakciojn. Post ĉio, via datumtavolo povas facile plenumi altnivelajn operaciojn sen krei siajn proprajn transakciojn. Krome, la komerca logiko mem kapablas komenci transakcion, fari operaciojn sur ĝi, fari aŭ ĉesigi transakcion.

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.

Transakcioj ne estu ligitaj al aplika stato

Kelkfoje estas tentante uzi aplikan staton en transakcioj por ŝanĝi certajn valorojn aŭ ĝustigi demandajn parametrojn. La kritika nuanco por konsideri estas la ĝusta amplekso de apliko. Klientoj ofte rekomencas transakciojn kiam estas retaj problemoj. Se la transakcio tiam dependas de stato, kiu estas ŝanĝita per iu alia procezo, ĝi povas elekti la malĝustan valoron depende de la ebleco de datumvetkuro. Transakcioj devas konsideri la riskon de datumvetkurkondiĉoj en la aplikaĵo.

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

La ĉi-supra transakcio pliigos la sinsekvon ĉiufoje kiam ĝi estas efektivigita, sendepende de la fina rezulto. Se la kommit malsukcesas pro retaj problemoj, la peto estos plenumita kun malsama sinsekvo kiam vi provos denove.

Demandaj planistoj povas diri al vi multon pri datumbazo

Demandaj planistoj determinas kiel demando estos efektivigita en datumbazo. Ili ankaŭ analizas petojn kaj optimumigas ilin antaŭ sendi ilin. Planistoj povas nur provizi iujn eblajn taksojn bazitajn sur la signaloj je ilia dispono. Ekzemple, kio estas la plej bona serĉmetodo por la sekva demando?

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

La rezultoj povas esti prenitaj en du manieroj:

  • Plena tablo-skanado: Vi povas rigardi ĉiun enskribon en la tabelo kaj resendi artikolojn kun kongrua aŭtoronomo, kaj poste mendi ilin.
  • Indeksa skanado: Vi povas uzi indekson por trovi kongruajn identigilojn, akiri tiujn vicojn, kaj poste ordigi ilin.

La tasko de la demandplanisto estas determini kiu strategio estas plej bona. Indas konsideri, ke konsultplanistoj nur havas limigitajn prognozajn kapablojn. Ĉi tio povas konduki al malbonaj decidoj. DBA-oj aŭ programistoj povas uzi ilin por diagnozi kaj agordi malsuperajn demandojn. Novaj versioj de la DBMS povas agordi konsultplanistojn, kaj mem-diagnozo povas helpi dum ĝisdatigado de la datumbazo se la nova versio kondukas al rendimentoproblemoj. Malrapidaj konsultaj protokoloj, raportoj pri latenteco aŭ statistikoj pri ekzekuttempo povas helpi identigi demandojn, kiuj bezonas optimumigon.

Kelkaj metrikoj prezentitaj de la demandplanisto povas esti kondiĉigitaj de bruo (precipe dum taksado de latenteco aŭ CPU-tempo). Bona aldono al planiloj estas iloj por spuri kaj spuri la ekzekutvojon. Ili permesas vin diagnozi tiajn problemojn (ve, ne ĉiuj DBMSoj provizas tiajn ilojn).

Reta migrado estas malfacila sed ebla

Reta migrado, viva migrado aŭ realtempa migrado signifas moviĝi de unu datumbazo al alia sen malfunkcio aŭ datuma korupto. Viva migrado estas pli facila por efektivigi se la transiro okazas ene de la sama DBMS/motoro. La situacio fariĝas pli komplika kiam necesas moviĝi al nova DBMS kun malsamaj agado kaj skemaj postuloj.

Estas malsamaj retaj migraj modeloj. Jen unu el ili:

  • Ebligu duoblan eniron en ambaŭ datumbazoj. La nova datumbazo en ĉi tiu etapo ne havas ĉiujn datumojn, sed nur akceptas la plej novajn datumojn. Post kiam vi estas certa pri tio, vi povas pluiri al la sekva paŝo.
  • Ebligu legadon de ambaŭ datumbazoj.
  • Agordu la sistemon tiel ke legado kaj skribo estu faritaj ĉefe sur la nova datumbazo.
  • Ĉesu skribi al la malnova datumbazo dum daŭre legas datumojn de ĝi. En ĉi tiu etapo, la nova datumbazo ankoraŭ estas sen iuj datumoj. Ili devus esti kopiitaj el la malnova datumbazo.
  • La malnova datumbazo estas nurlegebla. Kopiu la mankantajn datumojn de la malnova datumbazo al la nova. Post kiam la migrado estas kompleta, ŝanĝu la vojojn al la nova datumbazo, kaj haltigu la malnovan kaj forigu ĝin de la sistemo.

Por pliaj informoj, mi rekomendas kontakti artikolo, kiu detaligas la migradan strategion de Stripe bazitan sur ĉi tiu modelo.

Signifa pliiĝo en la datumbazo kunportas pliiĝon de neantaŭvidebleco

La kresko de la datumbazo kondukas al neantaŭvideblaj problemoj asociitaj kun ĝia skalo. Ju pli ni scias pri la interna strukturo de datumbazo, des pli bone ni povas antaŭdiri kiel ĝi skalos. Tamen iuj momentoj estas ankoraŭ neeble antaŭvidi.
Dum la bazo kreskas, antaŭaj supozoj kaj atendoj pri datumvolumeno kaj retaj bendolarĝaj postuloj povas malnoviĝi. Ĉi tio estas kiam la demando ekestas pri gravaj dezajnorevizioj, grandskalaj funkciaj plibonigoj, repripensado de deplojoj aŭ migrado al aliaj DBMSoj por eviti eblajn problemojn.

Sed ne pensu, ke bonega scio pri la interna strukturo de la ekzistanta datumbazo estas la sola necesa. Novaj pesiloj kunportos novajn nekonatojn. Neantaŭvideblaj dolorpunktoj, malebena distribuo de datumoj, neatenditaj bendolarĝoj kaj aparataj problemoj, ĉiam kreskanta trafiko kaj novaj retsegmentoj devigos vin repripensi vian datumbazan aliron, datummodelon, deplojan modelon kaj datumbazgrandecon.

...

Tiutempe mi ekpensis pri publikigo de ĉi tiu artikolo, jam estis kvin pliaj eroj en mia originala listo. Poste venis grandega nombro novaj ideoj pri kio alia povas esti kovrita. Tial la artikolo tuŝas la malplej evidentajn problemojn, kiuj postulas maksimuman atenton. Tamen tio ne signifas, ke la temo elĉerpiĝis kaj mi ne plu revenos al ĝi en miaj estontaj materialoj kaj ne faros ŝanĝojn al la nuna.

PS

Legu ankaŭ en nia blogo:

fonto: www.habr.com

Aldoni komenton