Daugiau kūrėjų turėtų tai žinoti apie duomenų bazes

Pastaba. vert.: Jaana Dogan yra patyrusi „Google“ inžinierė, šiuo metu dirbanti su „Go“ parašytų įmonės gamybos paslaugų stebėjimu. Šiame straipsnyje, kuris sulaukė didelio populiarumo tarp angliškai kalbančios auditorijos, ji 17 punktų surinko svarbias technines detales, susijusias su DBVS (o kartais ir apskritai paskirstytomis sistemomis), į kurias naudinga atsižvelgti didelių / reiklių programų kūrėjams.

Daugiau kūrėjų turėtų tai žinoti apie duomenų bazes

Didžioji dauguma kompiuterinių sistemų seka savo būseną ir, atitinkamai, reikalauja tam tikros duomenų saugojimo sistemos. Per ilgą laiką kaupiau žinias apie duomenų bazes, pakeliui padarydamas projektavimo klaidų, dėl kurių buvo prarasti duomenys ir dingimai. Sistemose, kurios apdoroja didelius informacijos kiekius, duomenų bazės yra sistemos architektūros pagrindas ir yra pagrindinis elementas renkantis optimalų sprendimą. Nepaisant to, kad duomenų bazės darbui skiriamas didelis dėmesys, problemos, kurias bando numatyti programų kūrėjai, dažnai yra tik ledkalnio viršūnė. Šioje straipsnių serijoje dalinuosi keletu idėjų, kurios bus naudingos kūrėjams, kurie nesispecializuoja šioje srityje.

  1. Jums pasisekė, jei 99,999 % atvejų tinklas nesukelia problemų.
  2. RŪGŠTIS reiškia daug skirtingų dalykų.
  3. Kiekviena duomenų bazė turi savo nuoseklumo ir izoliacijos užtikrinimo mechanizmus.
  4. Optimistinis blokavimas gelbsti, kai sunku išlaikyti įprastą.
  5. Be nešvaraus skaitymo ir duomenų praradimo, yra ir kitų anomalijų.
  6. Duomenų bazė ir vartotojas ne visada sutaria dėl veiksmų eigos.
  7. Programos lygio atskyrimas gali būti perkeltas už programos ribų.
  8. Automatinis padidėjimas gali būti pavojingas.
  9. Pasenę duomenys gali būti naudingi ir jų nereikia užrakinti.
  10. Iškraipymai būdingi bet kokiems laiko šaltiniams.
  11. Vėlavimas turi daug reikšmių.
  12. Reikėtų įvertinti konkretaus sandorio našumo reikalavimus.
  13. Įdėtos operacijos gali būti pavojingos.
  14. Sandoriai neturėtų būti susieti su programos būsena.
  15. Užklausų planuotojai gali daug pasakyti apie duomenų bazes.
  16. Perėjimas internetu yra sudėtingas, bet įmanomas.
  17. Žymus duomenų bazės padidėjimas padidina nenuspėjamumą.

Norėčiau padėkoti Emmanuel Odeke, Rein Henrichs ir kitiems už atsiliepimus apie ankstesnę šio straipsnio versiją.

Jums pasisekė, jei 99,999 % atvejų tinklas nesukelia problemų.

Lieka klausimas, kiek patikimos yra šiuolaikinės tinklo technologijos ir kaip dažnai sistemos sugenda dėl tinklo gedimų. Informacijos šiuo klausimu yra nedaug, o tyrimuose dažnai dominuoja didelės organizacijos, turinčios specializuotus tinklus, įrangą ir personalą.

„Spanner“ („Google“ visame pasaulyje platinama duomenų bazė) pasiekiamumo lygis yra 99,999 %, todėl „Google“ tvirtina, kad tik 7,6% problemos yra susijusios su tinklu. Tuo pačiu metu bendrovė savo specializuotą tinklą vadina „pagrindiniu aukšto prieinamumo ramsčiu“. Studijuoti Bailis ir Kingsbury, atlikta 2014 m., meta iššūkį vienam iš „klaidingos nuomonės apie paskirstytą skaičiavimą“, kurį Peteris Deutschas suformulavo 1994 m. Ar tinklas tikrai patikimas?

Išsamių tyrimų už milžiniškų įmonių ribų, atliekamų platesniam internetui, tiesiog nėra. Taip pat nėra pakankamai duomenų iš pagrindinių žaidėjų, kiek procentų jų klientų problemų yra susijusios su tinklu. Puikiai žinome apie didelių debesų paslaugų teikėjų tinklo krūvos sutrikimus, kurie gali kelioms valandoms nuimti visą interneto dalį vien dėl to, kad tai aukšto lygio įvykiai, paveikiantys daug žmonių ir įmonių. Tinklo nutrūkimai gali sukelti problemų daug daugiau atvejų, net jei ne visi tie atvejai yra dėmesio centre. Debesijos paslaugų klientai taip pat nieko nežino apie problemų priežastis. Jei įvyko gedimas, tai beveik neįmanoma priskirti tinklo klaidai paslaugų teikėjo pusėje. Jiems trečiųjų šalių paslaugos yra juodosios dėžės. Neįmanoma įvertinti poveikio, jei nėra didelio paslaugų teikėjo.

Atsižvelgiant į tai, ką didieji žaidėjai praneša apie savo sistemas, galima drąsiai teigti, kad jums pasisekė, jei tinklo sunkumai sudaro tik nedidelę dalį galimų prastovų problemų. Tinklo ryšiai vis dar kenčia nuo tokių kasdienių dalykų, kaip aparatinės įrangos gedimai, topologijos pokyčiai, administracinės konfigūracijos pakeitimai ir elektros energijos tiekimo sutrikimai. Neseniai nustebau sužinojęs, kad galimų problemų sąrašas buvo įtrauktas ryklio įkandimai (taip, girdėjote teisingai).

RŪGŠTIS reiškia daug skirtingų dalykų

Akronimas ACID reiškia atomiškumą, nuoseklumą, izoliaciją, patikimumą. Šios operacijų savybės yra skirtos užtikrinti jų galiojimą gedimų, klaidų, techninės įrangos gedimų ir pan. Be ACID ar panašių schemų programų kūrėjams būtų sunku atskirti, už ką jie atsakingi, ir už ką atsakinga duomenų bazė. Dauguma reliacinių operacijų duomenų bazių stengiasi būti suderinamos su ACID, tačiau taikant naujus metodus, pvz., NoSQL, atsirado daug duomenų bazių be ACID operacijų, nes jas įgyvendinti brangu.

Kai pirmą kartą įstojau į pramonę, mūsų techninis vadovas kalbėjo apie ACID koncepcijos svarbą. Teisybės dėlei reikia pasakyti, kad ACID laikomas apytiksliu aprašymu, o ne griežtu įgyvendinimo standartu. Šiandien manau, kad tai daugiausia naudinga, nes iškelia tam tikrą problemų kategoriją (ir siūlo įvairius galimus sprendimus).

Ne kiekviena DBVS yra suderinama su ACID; Tuo pačiu metu duomenų bazių diegimas, palaikantis ACID, skirtingai supranta reikalavimų rinkinį. Viena iš priežasčių, kodėl ACID diegimas yra nevientisas, yra dėl daugybės kompromisų, kurių reikia imtis norint įgyvendinti ACID reikalavimus. Kūrėjai gali pateikti savo duomenų bazes kaip suderinamas su ACID, tačiau kraštutinių atvejų interpretacija gali labai skirtis, kaip ir „netikėtinų“ įvykių tvarkymo mechanizmas. Bent jau kūrėjai gali įgyti aukšto lygio supratimą apie bazinių diegimų sudėtingumą, kad tinkamai suprastų jų ypatingą elgesį ir dizaino kompromisus.

Diskusijos apie tai, ar MongoDB atitinka ACID reikalavimus, tęsiasi net ir po 4 versijos išleidimo. „MongoDB“ ilgą laiką nebuvo palaikoma medienos ruoša, nors pagal numatytuosius nustatymus duomenys buvo įkeliami į diską ne dažniau kaip kartą per 60 sekundžių. Įsivaizduokite tokį scenarijų: programa paskelbia du įrašus (w1 ir w2). MongoDB sėkmingai saugo w1, bet w2 prarandamas dėl aparatinės įrangos gedimo.

Daugiau kūrėjų turėtų tai žinoti apie duomenų bazes
Diagrama, iliustruojanti scenarijų. „MongoDB“ užstringa dar nespėjęs įrašyti duomenų į diską

Įsipareigojimas į diską yra brangus procesas. Vengdami dažnų įsipareigojimų, kūrėjai pagerina įrašymo našumą patikimumo sąskaita. Šiuo metu MongoDB palaiko registravimą, tačiau nešvarūs įrašai vis tiek gali paveikti duomenų vientisumą, nes pagal numatytuosius nustatymus žurnalai fiksuojami kas 100 ms. Tai yra, panašus scenarijus vis dar galimas žurnalams ir juose pateikiamiems pokyčiams, nors rizika yra daug mažesnė.

Kiekviena duomenų bazė turi savo nuoseklumo ir izoliavimo mechanizmus

Iš ACID reikalavimų nuoseklumas ir izoliacija gali pasigirti didžiausiu skirtingų įgyvendinimų skaičiumi, nes kompromisų spektras yra platesnis. Reikia pasakyti, kad nuoseklumas ir izoliacija yra gana brangios funkcijos. Jie reikalauja koordinavimo ir padidina konkurenciją dėl duomenų nuoseklumo. Problemos sudėtingumas žymiai padidėja, kai reikia horizontaliai išplėsti duomenų bazę keliuose duomenų centruose (ypač jei jie yra skirtinguose geografiniuose regionuose). Labai sunku pasiekti aukštą nuoseklumo lygį, nes tai taip pat sumažina pasiekiamumą ir padidina tinklo segmentaciją. Norėdami plačiau paaiškinti šį reiškinį, patariu kreiptis į BŽŪP teorema. Taip pat verta paminėti, kad programos gali susidoroti su nedideliais neatitikimų kiekiais, o programuotojai gali pakankamai gerai suprasti problemos niuansus, kad įdiegtų papildomą logiką programoje, kuri tvarkytų nenuoseklumą, nepasitikėdami duomenų baze.

DBVS dažnai suteikia skirtingus izoliacijos lygius. Programų kūrėjai gali pasirinkti efektyviausią pagal savo pageidavimus. Maža izoliacija leidžia padidinti greitį, bet taip pat padidina duomenų lenktynių riziką. Aukšta izoliacija sumažina šią tikimybę, tačiau lėtina darbus ir gali sukelti konkurenciją, dėl kurios bazėje atsiras tokie stabdžiai, kad prasidės gedimai.

Daugiau kūrėjų turėtų tai žinoti apie duomenų bazes
Esamų lygiagrečių modelių ir ryšių tarp jų apžvalga

SQL standartas apibrėžia tik keturis izoliacijos lygius, nors teoriškai ir praktikoje jų yra daug daugiau. Jepson.io siūlo puikią esamų lygiagretumo modelių apžvalgą. Pavyzdžiui, „Google Spanner“ garantuoja išorinį serializavimą su laikrodžio sinchronizavimu, ir nors tai yra griežtesnis izoliavimo sluoksnis, jis nėra apibrėžtas standartiniuose izoliacijos sluoksniuose.

SQL standartas nurodo šiuos izoliacijos lygius:

  • Serijinis (griežčiausias ir brangiausias): nuoseklus vykdymas turi tokį patį poveikį kaip ir kai kurių nuoseklių operacijų vykdymas. Nuoseklus vykdymas reiškia, kad kiekviena paskesnė operacija pradedama tik po to, kai baigiama ankstesnė. Reikėtų pažymėti, kad lygis Serijinis dažnai įgyvendinamas kaip vadinamasis momentinės nuotraukos izoliavimas (pavyzdžiui, „Oracle“) dėl interpretacijos skirtumų, nors pats momentinės nuotraukos izoliavimas nėra pateiktas SQL standarte.
  • Pakartojami skaitymai: neįsipareigoti dabartinės operacijos įrašai yra prieinami dabartinei operacijai, tačiau kitų operacijų atlikti pakeitimai (pvz., naujos eilutės) nematomas.
  • Skaityti įsipareigojo: Neįsipareigoti operacijų duomenys nepasiekiami. Tokiu atveju operacijos gali matyti tik priskirtus duomenis ir gali įvykti fantominiai nuskaitymai. Jei operacija įterpia ir patvirtina naujas eilutes, dabartinė operacija galės jas matyti, kai bus pateikta užklausa.
  • Skaityti neįsipareigojęs (mažiausias griežtas ir brangus lygis): Leidžiamas nešvarus skaitymas, operacijose gali būti matomi neįsipareigoti kitų operacijų pakeitimai. Praktiškai šis lygis gali būti naudingas atliekant apytikslius įvertinimus, pvz., užklausas COUNT(*) ant stalo.

Lygis Serijinis sumažina duomenų lenktynių riziką, tuo pačiu yra brangiausia įdiegti ir dėl to sistemos konkurencinė apkrova yra didžiausia. Kitus izoliacijos lygius lengviau įgyvendinti, tačiau padidėja duomenų lenktynių tikimybė. Kai kurios DBVS leidžia nustatyti pasirinktinį izoliacijos lygį, kitos turi stiprias nuostatas ir ne visi lygiai palaikomi.

Atskyrimo lygių palaikymas dažnai reklamuojamas tam tikroje DBVS, tačiau tik kruopštus jos elgesio tyrimas gali atskleisti, kas iš tikrųjų vyksta.

Daugiau kūrėjų turėtų tai žinoti apie duomenų bazes
Vienalaikio anomalijų peržiūra skirtinguose skirtingų DBVS izoliacijos lygiuose

Martin Kleppmann savo projekte ermitažas Lygina skirtingus izoliacijos lygius, kalba apie lygiagretumo anomalijas ir apie tai, ar duomenų bazė gali laikytis tam tikro izoliacijos lygio. Kleppmanno tyrimas rodo, kaip skirtingai duomenų bazių kūrėjai galvoja apie izoliacijos lygius.

Optimistinis blokavimas gelbsti, kai sunku išlaikyti įprastą.

Blokavimas gali būti labai brangus ne tik todėl, kad padidina konkurenciją duomenų bazėje, bet ir todėl, kad programų serveriai turi nuolat prisijungti prie duomenų bazės. Tinklo segmentavimas gali pabloginti išskirtines užrakinimo situacijas ir sukelti aklavietes, kurias sunku nustatyti ir išspręsti. Tais atvejais, kai išskirtinis užraktas netinka, padeda optimistinis užrakinimas.

Optimistiškas užraktas yra metodas, kai skaitydama eilutę atsižvelgiama į jos versiją, kontrolinę sumą arba paskutinio pakeitimo laiką. Tai leidžia užtikrinti, kad prieš keisdami įrašą nebūtų pakeista atominė versija:

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

Šiuo atveju atnaujinama lentelė products nebus atlikta, jei šioje eilutėje anksčiau buvo atlikta kita operacija. Jei šioje eilutėje nebuvo atlikta jokių kitų operacijų, vienos eilutės pakeitimas įvyks ir galime sakyti, kad atnaujinimas buvo sėkmingas.

Be nešvaraus skaitymo ir duomenų praradimo, yra ir kitų anomalijų

Kalbant apie duomenų nuoseklumą, didžiausias dėmesys skiriamas galimoms lenktynių sąlygoms, kurios gali sukelti nešvarų skaitymą ir duomenų praradimą. Tačiau duomenų anomalijos tuo nesibaigia.

Vienas iš tokių anomalijų pavyzdžių yra įrašymo iškraipymas (rašyti įstrižai). Iškraipymus sunku aptikti, nes paprastai jų nėra aktyviai ieškoma. Jie atsiranda ne dėl nešvaraus skaitymo ar duomenų praradimo, o dėl loginių duomenų suvaržymų pažeidimų.

Pavyzdžiui, apsvarstykime stebėjimo programą, kuriai reikia, kad vienas operatorius visą laiką budėtų:

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;

Aukščiau pateiktoje situacijoje, jei abi operacijos bus sėkmingai įvykdytos, įvyks rekordinė korupcija. Nors nebuvo nešvarių nuskaitymų ar duomenų praradimo, duomenų vientisumas buvo pažeistas: dabar budinčiais vienu metu laikomi du žmonės.

Serializuojama izoliacija, schemos projektavimas arba duomenų bazės apribojimai gali padėti pašalinti rašymo pažeidimus. Kūrėjai turi sugebėti nustatyti tokias anomalijas kūrimo metu, kad jų išvengtų gamyboje. Tuo pačiu metu kodų bazėje labai sunku ieškoti įrašymo iškraipymų. Ypač didelėse sistemose, kai skirtingos kūrėjų komandos yra atsakingos už funkcijų įgyvendinimą pagal tas pačias lenteles ir nesutaria dėl duomenų prieigos specifikos.

Duomenų bazė ir vartotojas ne visada sutaria, ką daryti

Viena iš pagrindinių duomenų bazių ypatybių yra vykdymo užsakymo garantija, tačiau pats šis užsakymas gali būti neskaidrus programinės įrangos kūrėjui. Duomenų bazės atlieka operacijas tokia tvarka, kokia jos gaunamos, o ne programuotojų numatyta tvarka. Sandorių eiliškumą sunku numatyti, ypač labai apkrautose lygiagrečiose sistemose.

Kūrimo metu, ypač dirbant su neblokuojančiomis bibliotekomis, prastas stilius ir prastas skaitomumas gali priversti vartotojus manyti, kad operacijos vykdomos nuosekliai, nors iš tikrųjų jos gali patekti į duomenų bazę bet kokia tvarka.

Iš pirmo žvilgsnio žemiau esančioje programoje T1 ir T2 iškviečiami nuosekliai, tačiau jei šios funkcijos neblokuoja ir iš karto grąžina rezultatą formoje pažadas, tada skambučių eiliškumą lems momentai, kada jie įėjo į duomenų bazę:

rezultatas1 = T1() // realūs rezultatai yra pažadai
rezultatas2 = T2()

Jei reikalingas atomiškumas (ty visos operacijos turi būti užbaigtos arba nutrauktos) ir svarbi seka, operacijos T1 ir T2 turi būti atliekamos per vieną operaciją.

Programos lygio atskyrimas gali būti perkeltas už programos ribų

Dalijimasis yra horizontalaus duomenų bazės skaidymo metodas. Kai kurios duomenų bazės gali automatiškai padalyti duomenis horizontaliai, o kitos negali arba nėra labai geros. Kai duomenų architektai / kūrėjai gali tiksliai numatyti, kaip bus pasiekti duomenys, jie gali sukurti horizontalius skirsnius vartotojo erdvėje, o ne deleguoti šį darbą duomenų bazei. Šis procesas vadinamas „programos lygio dalijimu“ (programos lygio dalijimasis).

Deja, šis pavadinimas dažnai sukuria klaidingą nuomonę, kad sharding gyvena taikomųjų programų paslaugose. Tiesą sakant, jis gali būti įdiegtas kaip atskiras sluoksnis priešais duomenų bazę. Priklausomai nuo duomenų augimo ir schemų iteracijų, dalijimosi reikalavimai gali tapti gana sudėtingi. Kai kurioms strategijoms gali būti naudinga galimybė kartoti neperskirstant taikomųjų programų serverių.

Daugiau kūrėjų turėtų tai žinoti apie duomenų bazes
Architektūros, kurioje taikomųjų programų serveriai yra atskirti nuo dalijimosi paslaugos, pavyzdys

Perkėlus dalijimąsi į atskirą paslaugą, išplečiama galimybė naudoti skirtingas dalijimo strategijas, nereikalaujant perskirstyti programų. Vitess yra tokios dalijimosi sistemos pavyzdys programos lygiu. „Vitess“ teikia „MySQL“ horizontalų skaidymą ir leidžia klientams prisijungti prie jo naudojant „MySQL“ protokolą. Sistema segmentuoja duomenis į skirtingus MySQL mazgus, kurie nieko nežino vienas apie kitą.

Automatinis padidėjimas gali būti pavojingas

AUTOMATINIS INCREMENT yra įprastas pirminių raktų generavimo būdas. Dažnai pasitaiko atvejų, kai duomenų bazės naudojamos kaip ID generatoriai, o duomenų bazėje yra lentelės, skirtos identifikatoriams generuoti. Yra keletas priežasčių, kodėl pirminių raktų generavimas naudojant automatinį padidinimą toli gražu nėra idealus:

  • Paskirstytoje duomenų bazėje automatinis didinimas yra rimta problema. Norint sugeneruoti ID, reikalingas visuotinis užraktas. Vietoj to galite sugeneruoti UUID: tam nereikia sąveikauti tarp skirtingų duomenų bazės mazgų. Automatinis padidinimas naudojant užraktus gali sukelti ginčus ir žymiai sumažinti įdėklų našumą paskirstytose situacijose. Kai kurioms DBVS (pavyzdžiui, MySQL) gali prireikti specialios konfigūracijos ir kruopštesnio dėmesio, kad būtų galima tinkamai organizuoti pagrindinio ir pagrindinio replikaciją. Be to, lengva padaryti klaidų konfigūruojant, o tai sukels įrašymo gedimus.
  • Kai kuriose duomenų bazėse yra skirstymo algoritmai, pagrįsti pirminiais raktais. Iš eilės ID gali sukelti nenuspėjamų karštųjų taškų ir padidėti kai kurių skaidinių apkrova, o kitos likti nenaudojamos.
  • Pirminis raktas yra greičiausias būdas pasiekti duomenų bazės eilutę. Naudojant geresnius įrašų identifikavimo būdus, nuoseklūs ID gali paversti svarbiausią lentelių stulpelį nenaudingu stulpeliu, užpildytu beprasmėmis reikšmėmis. Todėl, kai tik įmanoma, pasirinkite visuotinai unikalų ir natūralų pirminį raktą (pvz., vartotojo vardą).

Prieš nuspręsdami dėl metodo, apsvarstykite automatinio ID ir UUID didinimo poveikį indeksavimui, skaidymui ir dalijimuisi.

Pasenę duomenys gali būti naudingi ir jų nereikia užrakinti

Daugiaversijų lygiagretumo valdymas (MVCC) įgyvendina daugelį nuoseklumo reikalavimų, kurie buvo trumpai aptarti aukščiau. Kai kurios duomenų bazės (pvz., „Postgres“, „Spanner“) naudoja MVCC, kad „pateiktų“ operacijas momentinėmis nuotraukomis – senesnėmis duomenų bazės versijomis. Kad būtų užtikrintas nuoseklumas, momentinės operacijos taip pat gali būti serijinės. Skaitant iš senos momentinės nuotraukos, nuskaitomi pasenę duomenys.

Šiek tiek pasenusių duomenų skaitymas gali būti naudingas, pavyzdžiui, generuojant analizę iš duomenų arba apskaičiuojant apytiksles bendras reikšmes.

Pirmasis darbo su senais duomenimis privalumas yra mažas delsimas (ypač jei duomenų bazė yra paskirstyta skirtingose ​​geografinėse vietovėse). Antrasis yra tas, kad tik skaitomos operacijos yra neužrakintos. Tai didelis privalumas programoms, kurios daug skaito, jei jos gali tvarkyti pasenusius duomenis.

Daugiau kūrėjų turėtų tai žinoti apie duomenų bazes
Programos serveris nuskaito duomenis iš vietinės kopijos, kuri yra pasenusi 5 sekundes, net jei naujausia versija yra kitoje Ramiojo vandenyno pusėje

DBVS automatiškai išvalo senesnes versijas ir kai kuriais atvejais leidžia tai padaryti paprašius. Pavyzdžiui, „Postgres“ leidžia vartotojams tai padaryti VACUUM paprašius, taip pat periodiškai automatiškai atlieka šią operaciją. Spanneris valdo šiukšlių rinktuvą, kad pašalintų senesnius nei vienos valandos momentines nuotraukas.

Bet kokie laiko šaltiniai gali būti iškraipyti

Geriausiai saugoma kompiuterių mokslo paslaptis yra ta, kad visos laiko API meluoja. Tiesą sakant, mūsų mašinos nežino tikslaus dabartinio laiko. Kompiuteriuose yra kvarco kristalų, kurie generuoja vibracijas, kurios yra naudojamos išlaikyti laiką. Tačiau jie nėra pakankamai tikslūs ir gali aplenkti / atsilikti nuo tikslaus laiko. Pamaina gali siekti 20 sekundžių per dieną. Todėl laikas mūsų kompiuteriuose turi būti periodiškai sinchronizuojamas su tinklo laiku.

Sinchronizavimui naudojami NTP serveriai, tačiau pats sinchronizavimo procesas gali užtrukti tinkle. Net sinchronizavimas su NTP serveriu tame pačiame duomenų centre užtrunka. Akivaizdu, kad darbas su viešu NTP serveriu gali sukelti dar didesnį iškraipymą.

Atominiai laikrodžiai ir jų GPS analogai yra geresni dabartiniam laikui nustatyti, tačiau jie yra brangūs ir reikalauja sudėtingo nustatymo, todėl negali būti montuojami kiekviename automobilyje. Dėl šios priežasties duomenų centrai naudoja pakopinį metodą. Atominiai ir/ar GPS laikrodžiai rodo tikslų laiką, po kurio jis per antrinius serverius transliuojamas į kitas mašinas. Tai reiškia, kad kiekviena mašina patirs tam tikrą nuokrypį nuo tikslaus laiko.

Padėtį apsunkina tai, kad programos ir duomenų bazės dažnai yra skirtinguose įrenginiuose (jei ne skirtinguose duomenų centruose). Taigi laikas skirsis ne tik DB mazguose, paskirstytuose įvairiose mašinose. Tai taip pat bus kitokia programų serveryje.

„Google TrueTime“ taiko visiškai kitokį požiūrį. Dauguma žmonių mano, kad „Google“ pažanga šia kryptimi paaiškinama banaliu perėjimu prie atominių ir GPS laikrodžių, tačiau tai tik dalis bendro vaizdo. Štai kaip veikia TrueTime:

  • „TrueTime“ naudoja du skirtingus šaltinius: GPS ir atominius laikrodžius. Šie laikrodžiai turi nesusijusius gedimo režimus. [daugiau informacijos rasite 5 puslapyje čia - apytiksliai vertimas.), todėl jų bendras naudojimas padidina patikimumą.
  • „TrueTime“ turi neįprastą API. Jis grąžina laiką kaip intervalą su matavimo paklaida ir neapibrėžtumu. Tikrasis laiko momentas yra kažkur tarp viršutinės ir apatinės intervalo ribų. Spanner, Google paskirstyta duomenų bazė, tiesiog laukia, kol bus saugu teigti, kad dabartinis laikas yra už diapazono ribų. Šis metodas įveda į sistemą tam tikrą delsą, ypač jei šeimininkų neapibrėžtumas yra didelis, tačiau užtikrina teisingumą net ir globaliai paskirstytoje situacijoje.

Daugiau kūrėjų turėtų tai žinoti apie duomenų bazes
Veržliarakčio komponentai naudoja TrueTime, kur TT.now() grąžina intervalą, todėl veržliaraktis tiesiog miega tol, kol gali būti tikras, kad dabartinis laikas praėjo tam tikrą tašką

Sumažėjęs dabartinio laiko nustatymo tikslumas reiškia, kad pailgėja veržliarakčio veikimo trukmė ir sumažėja našumas. Štai kodėl svarbu išlaikyti didžiausią įmanomą tikslumą, net jei neįmanoma gauti visiškai tikslaus laikrodžio.

Vėlavimas turi daug reikšmių

Jei paklausite tuzino ekspertų, kas yra vėlavimas, tikriausiai gausite skirtingus atsakymus. DBVS delsa dažnai vadinama „duomenų bazės delsa“ ir skiriasi nuo to, ką suvokia klientas. Faktas yra tas, kad klientas stebi tinklo vėlavimo ir duomenų bazės vėlavimo sumą. Gebėjimas išskirti delsos tipą yra labai svarbus derinant didėjančias problemas. Rinkdami ir rodydami metriką visada stenkitės stebėti abu tipus.

Reikėtų įvertinti konkretaus sandorio našumo reikalavimus

Kartais DBVS veikimo charakteristikos ir jos apribojimai nurodomi rašymo / skaitymo pralaidumo ir delsos požiūriu. Tai suteikia bendrą pagrindinių sistemos parametrų apžvalgą, tačiau vertinant naujos DBVS našumą, daug išsamesnis požiūris yra atskirai įvertinti svarbias operacijas (kiekvienai užklausai ir (arba) operacijai). Pavyzdžiai:

  • Rašykite pralaidumą ir delsą įterpdami naują eilutę į lentelę X (su 50 milijonų eilučių) su nurodytais apribojimais ir eilučių užpildymu susijusiose lentelėse.
  • Vėlavimas rodyti tam tikro vartotojo draugų draugus, kai vidutinis draugų skaičius yra 500.
  • 100 populiariausių įrašų gavimo delsa iš vartotojo istorijos, kai vartotojas seka 500 kitų naudotojų su X įrašais per valandą.

Vertinimas ir eksperimentavimas gali apimti tokius kritinius atvejus, kol būsite tikri, kad duomenų bazė atitinka našumo reikalavimus. Taikant panašią nykščio taisyklę taip pat atsižvelgiama į šį skirstymą renkant delsos metriką ir nustatant SLO.

Rinkdami kiekvienos operacijos metriką, atkreipkite dėmesį į didelį kardinalumą. Naudokite žurnalus, įvykių rinkinį arba paskirstytą sekimą, kad gautumėte didelės galios derinimo duomenis. Straipsnyje "Norite derinti delsą?» galite susipažinti su vėlavimo derinimo metodikomis.

Įdėtos operacijos gali būti pavojingos

Ne kiekviena DBVS palaiko įdėtas operacijas, tačiau kai jos palaikomos, tokios operacijos gali sukelti netikėtų klaidų, kurias ne visada lengva aptikti (tai yra, turėtų būti akivaizdu, kad yra kažkokia anomalija).

Galite nenaudoti įdėtųjų operacijų naudodami klientų bibliotekas, kurios gali jas aptikti ir apeiti. Jei įdėtųjų operacijų negalima atsisakyti, būkite ypač atsargūs jas įgyvendindami, kad išvengtumėte netikėtų situacijų, kai užbaigtos operacijos netyčia nutraukiamos dėl įdėtųjų.

Sandorių įtraukimas į skirtingus sluoksnius gali sukelti netikėtas įdėtas operacijas, o kodo skaitomumo požiūriu gali būti sunku suprasti autoriaus ketinimus. Pažvelkite į šią programą:

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

Kokia bus aukščiau pateikto kodo išvestis? Ar jis atšauks abu sandorius, ar tik vidinį? Kas atsitiks, jei pasikliausime keliais bibliotekų sluoksniais, kurie apima operacijų kūrimą už mus? Ar pavyks tokius atvejus nustatyti ir patobulinti?

Įsivaizduokite duomenų sluoksnį su keliomis operacijomis (pvz., newAccount) jau įdiegtas jos pačios sandoriuose. Kas atsitiks, jei vykdysite juos kaip aukštesnio lygio verslo logikos, kuri vykdoma per savo sandorį, dalį? Kokia būtų izoliacija ir nuoseklumas šiuo atveju?

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

Užuot ieškojus atsakymų į tokius begalinius klausimus, geriau vengti įdėtųjų operacijų. Galų gale, jūsų duomenų sluoksnis gali lengvai atlikti aukšto lygio operacijas nesukurdamas savo operacijų. Be to, pati verslo logika gali inicijuoti sandorį, atlikti su ja susijusias operacijas, įvykdyti ar nutraukti sandorį.

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.

Sandoriai neturėtų būti susieti su programos būsena

Kartais kyla pagunda operacijose naudoti programos būseną, kad būtų galima pakeisti tam tikras reikšmes arba koreguoti užklausos parametrus. Svarbus niuansas, į kurį reikia atsižvelgti, yra teisinga taikymo sritis. Klientai dažnai iš naujo paleidžia operacijas, kai kyla tinklo problemų. Jei tada operacija priklauso nuo būsenos, kurią keičia koks nors kitas procesas, ji gali pasirinkti neteisingą reikšmę, atsižvelgiant į duomenų lenktynių galimybę. Operacijose turi būti atsižvelgta į duomenų lenktynių sąlygų riziką programoje.

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

Aukščiau nurodytos operacijos eilės numeris bus padidintas kiekvieną kartą, kai ji bus vykdoma, neatsižvelgiant į galutinį rezultatą. Jei įsipareigojimas nepavyksta dėl tinklo problemų, užklausa bus vykdoma su kitu eilės numeriu, kai bandysite dar kartą.

Užklausų planuotojai gali daug pasakyti apie duomenų bazę

Užklausų planuotojai nustato, kaip užklausa bus vykdoma duomenų bazėje. Jie taip pat analizuoja užklausas ir optimizuoja jas prieš siųsdami. Planuotojai gali pateikti tik kai kuriuos galimus įvertinimus, pagrįstus jų turimais signalais. Pavyzdžiui, koks yra geriausias paieškos metodas pagal šią užklausą?

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

Rezultatus galima gauti dviem būdais:

  • Visas lentelės nuskaitymas: galite peržiūrėti kiekvieną lentelės įrašą ir grąžinti straipsnius su atitinkančiu autoriaus vardu, tada juos užsisakyti.
  • Indekso nuskaitymas: galite naudoti rodyklę, kad rastumėte atitinkančius ID, gautumėte tas eilutes ir jas sutvarkytumėte.

Užklausų planuotojo užduotis yra nustatyti, kuri strategija yra geriausia. Verta manyti, kad užklausų planavimo priemonės turi tik ribotas nuspėjamąsias galimybes. Tai gali lemti blogus sprendimus. DBA arba kūrėjai gali juos naudoti norėdami diagnozuoti ir koreguoti prastai veikiančias užklausas. Naujos DBVS versijos gali konfigūruoti užklausų planavimo priemones, o savidiagnostika gali padėti atnaujinant duomenų bazę, jei naujoji versija sukelia našumo problemų. Lėti užklausų žurnalai, vėlavimo problemų ataskaitos arba vykdymo laiko statistika gali padėti nustatyti užklausas, kurias reikia optimizuoti.

Kai kurios užklausų planavimo priemonės pateiktos metrikos gali būti triukšmingos (ypač įvertinant delsą arba procesoriaus laiką). Geras planavimo priemonių papildymas yra įrankiai, skirti sekti ir sekti vykdymo kelią. Jie leidžia diagnozuoti tokias problemas (deja, ne visos DBVS teikia tokius įrankius).

Perėjimas internetu yra sudėtingas, bet įmanomas

Perkėlimas internetu, tiesioginis perkėlimas arba perkėlimas realiuoju laiku reiškia perėjimą iš vienos duomenų bazės į kitą be prastovų ar duomenų sugadinimo. Tiesioginį perkėlimą lengviau atlikti, jei perėjimas vyksta toje pačioje DBVS / variklyje. Situacija tampa sudėtingesnė, kai reikia pereiti prie naujos DBVS su skirtingais našumo ir schemos reikalavimais.

Yra įvairių internetinės migracijos modelių. Štai vienas iš jų:

  • Įgalinti dvigubą įrašą abiejose duomenų bazėse. Naujoji duomenų bazė šiame etape neturi visų duomenų, o priima tik naujausius duomenis. Kai tuo įsitikinsite, galite pereiti prie kito žingsnio.
  • Įgalinti skaitymą iš abiejų duomenų bazių.
  • Sukonfigūruokite sistemą taip, kad skaitymas ir rašymas pirmiausia būtų atliekami naujoje duomenų bazėje.
  • Nustokite rašyti į seną duomenų bazę ir toliau skaityti duomenis iš jos. Šiame etape naujoje duomenų bazėje vis dar trūksta kai kurių duomenų. Jie turėtų būti nukopijuoti iš senos duomenų bazės.
  • Senoji duomenų bazė yra tik skaitoma. Nukopijuokite trūkstamus duomenis iš senosios duomenų bazės į naują. Baigę perkėlimą, perjunkite kelius į naują duomenų bazę, sustabdykite senąją ir ištrinkite ją iš sistemos.

Dėl papildomos informacijos rekomenduoju kreiptis straipsnis, kuriame išsamiai aprašyta „Stripe“ perkėlimo strategija, pagrįsta šiuo modeliu.

Žymus duomenų bazės padidėjimas padidina nenuspėjamumą

Duomenų bazės augimas sukelia nenuspėjamų problemų, susijusių su jos mastu. Kuo daugiau žinome apie vidinę duomenų bazės struktūrą, tuo geriau galime numatyti jos mastelį. Tačiau kai kurių akimirkų vis tiek neįmanoma numatyti.
Augant bazei, ankstesnės prielaidos ir lūkesčiai dėl duomenų apimties ir tinklo pralaidumo reikalavimų gali pasenti. Tai yra tada, kai kyla klausimas dėl esminių projektavimo remonto, didelio masto veiklos patobulinimų, diegimo persvarstymo arba perkėlimo į kitas DBVS, kad būtų išvengta galimų problemų.

Tačiau nemanykite, kad reikia tik puikios esamos duomenų bazės vidinės struktūros išmanymo. Naujos svarstyklės atneš naujų nežinomųjų. Neprognozuojami skausmo taškai, netolygus duomenų paskirstymas, netikėtos pralaidumo ir aparatinės įrangos problemos, nuolat didėjantis srautas ir nauji tinklo segmentai privers permąstyti duomenų bazės metodą, duomenų modelį, diegimo modelį ir duomenų bazės dydį.

...

Tuo metu, kai pradėjau galvoti apie šio straipsnio publikavimą, mano pirminiame sąraše jau buvo dar penki elementai. Tada atėjo didžiulis skaičius naujų idėjų apie tai, ką dar galima padengti. Todėl straipsnyje paliečiamos mažiausiai akivaizdžios problemos, kurioms reikia maksimalaus dėmesio. Tačiau tai nereiškia, kad tema išsemta ir prie jos nebegrįšiu savo būsimoje medžiagoje ir nedarysiu dabartinės pakeitimų.

PS

Taip pat skaitykite mūsų tinklaraštyje:

Šaltinis: www.habr.com

Добавить комментарий