InterSystems IRIS DBMS palaiko įdomias duomenų saugojimo struktūras – globalius. Iš esmės tai yra kelių lygių raktai su įvairiomis papildomomis gėrybėmis operacijų pavidalu, greitomis duomenų medžių perėjimo funkcijomis, spynomis ir savo „ObjectScript“ kalba.
Plačiau apie globalius skaitykite straipsnių cikle „Globalai – lobis-kardai duomenims saugoti“:
Pradėjau domėtis, kaip globaliuose realizuojami sandoriai, kokios ten funkcijos. Juk tai visiškai kitokia duomenų saugojimo struktūra nei įprastos lentelės. Daug žemesnis lygis.
Kaip žinoma iš reliacinių duomenų bazių teorijos, geras operacijų įgyvendinimas turi atitikti reikalavimus :
A – Atominis (atomiškumas). Visi operacijos pakeitimai arba iš viso nėra įrašomi.
C – nuoseklumas. Užbaigus operaciją, loginė duomenų bazės būsena turi būti viduje nuosekli. Daugeliu atžvilgių šis reikalavimas susijęs su programuotoju, tačiau SQL duomenų bazių atveju jis taip pat susijęs su išoriniais raktais.
Aš - Izoliuok. Lygiagrečiai vykdomos operacijos neturėtų turėti įtakos viena kitai.
D – patvarus. Sėkmingai užbaigus operaciją, žemesnio lygio problemos (pavyzdžiui, elektros energijos tiekimo sutrikimas) neturėtų turėti įtakos duomenims, kuriuos pakeitė operacija.
Globalios yra nesusijusios duomenų struktūros. Jie buvo sukurti taip, kad veiktų labai greitai naudojant labai ribotą aparatinę įrangą. Pažvelkime į operacijų įgyvendinimą globaliuose naudojant .
Norint palaikyti operacijas IRIS, naudojamos šios komandos: , , .
1. Atomiškumas
Lengviausias būdas patikrinti atomiškumą. Tikriname iš duomenų bazės konsolės.
Kill ^a
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
TCOMMITTada darome išvadą:
Write ^a(1), “ ”, ^a(2), “ ”, ^a(3)Mes gauname:
1 2 3Viskas gerai. Išlaikomas atomiškumas: registruojami visi pokyčiai.
Apsunkinkime užduotį, įveskime klaidą ir pažiūrėkime, kaip operacija išsaugoma iš dalies ar iš viso.
Dar kartą patikrinkime atomiškumą:
Kill ^A
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3Tada mes jėga sustabdysime konteinerį, paleisime jį ir pamatysime.
docker kill my-irisŠi komanda beveik prilygsta priverstiniam išjungimui, nes siunčia SIGKILL signalą, kad procesas būtų nedelsiant sustabdytas.
Galbūt sandoris buvo iš dalies išsaugotas?
WRITE ^a(1), ^a(2), ^a(3)
^
<UNDEFINED> ^a(1)– Ne, neišliko.
Pabandykime grąžinimo komandą:
Kill ^A
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
TROLLBACK
WRITE ^a(1), ^a(2), ^a(3)
^
<UNDEFINED> ^a(1)Nieko taip pat neišliko.
2. Nuoseklumas
Kadangi duomenų bazėse, pagrįstose globaliais, raktai taip pat daromi ant globalių (priminsiu, kad globalas yra žemesnio lygio struktūra duomenims saugoti nei reliacinė lentelė), kad atitiktų nuoseklumo reikalavimą, turi būti įtrauktas rakto pakeitimas. tame pačiame sandoryje kaip ir globalaus pokytis.
Pavyzdžiui, turime visuotinį ^asmenį, kuriame saugome asmenybes ir kaip raktą naudojame TIN.
^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
...Norėdami greitai ieškoti pagal pavardę ir vardą, padarėme ^index klavišą.
^index(‘Kamenev’, ‘Sergey’, 1234567) = 1Kad duomenų bazė būtų nuosekli, turime pridėti asmenį taip:
TSTART
^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
^index(‘Kamenev’, ‘Sergey’, 1234567) = 1
TCOMMITAtitinkamai, ištrindami taip pat turime naudoti operaciją:
TSTART
Kill ^person(1234567)
ZKill ^index(‘Kamenev’, ‘Sergey’, 1234567)
TCOMMITKitaip tariant, nuoseklumo reikalavimo įvykdymas visiškai gula ant programuotojo pečių. Bet kalbant apie globalius, tai normalu dėl jų žemo lygio.
3. Izoliacija
Čia prasideda laukinės gamtos. Daugelis vartotojų vienu metu dirba su ta pačia duomenų baze, keisdami tuos pačius duomenis.
Situaciją galima palyginti su tuo, kai daug vartotojų vienu metu dirba su ta pačia kodo saugykla ir vienu metu bando atlikti daugelio failų pakeitimus vienu metu.
Duomenų bazė turėtų viską sutvarkyti realiu laiku. Atsižvelgiant į tai, kad rimtose įmonėse yra net specialus asmuo, kuris yra atsakingas už versijų kontrolę (už filialų sujungimą, konfliktų sprendimą ir pan.), o duomenų bazė turi visa tai daryti realiu laiku, užduoties sudėtingumas ir teisingumas. duomenų bazės dizainas ir jį aptarnaujantis kodas.
Duomenų bazė negali suprasti vartotojų atliekamų veiksmų reikšmės, kad išvengtų konfliktų, jei jie dirba su tais pačiais duomenimis. Jis gali anuliuoti tik vieną operaciją, kuri prieštarauja kitai, arba jas vykdyti nuosekliai.
Kita problema yra ta, kad operacijos vykdymo metu (prieš įsipareigojimą) duomenų bazės būsena gali būti nenuosekli, todėl pageidautina, kad kitos operacijos neturėtų prieigos prie nenuoseklios duomenų bazės būsenos, kuri pasiekiama reliacinėse duomenų bazėse. įvairiais būdais: kuriant momentines nuotraukas, kelių versijų eilutes ir pan.
Vykdant operacijas lygiagrečiai, mums svarbu, kad jos netrukdytų viena kitai. Tai yra izoliacijos savybė.
SQL apibrėžia 4 izoliacijos lygius:
- SKAITYTI NEĮSipareigotas
- SKAITYKITE ĮSIPAREIGOJĘ
- PAKARTOMAS SKAITYMAS
- SERIALIZUOJAMAS
Pažvelkime į kiekvieną lygį atskirai. Kiekvieno lygio diegimo išlaidos auga beveik eksponentiškai.
SKAITYTI NEĮSipareigotas – tai žemiausias izoliacijos lygis, bet kartu ir greičiausias. Sandoriai gali nuskaityti vienas kito atliktus pakeitimus.
SKAITYKITE ĮSIPAREIGOJĘ yra kitas izoliacijos lygis, o tai yra kompromisas. Sandoriai negali nuskaityti vienas kito pakeitimų prieš įsipareigojimą, bet gali perskaityti visus pakeitimus, padarytus po įsipareigojimo.
Jei turime ilgą transakciją T1, kurios metu commitai vyko operacijose T2, T3 ... Tn, kurios veikė su tais pačiais duomenimis kaip ir T1, tai užklausę duomenų T1 kiekvieną kartą gausime skirtingą rezultatą. Šis reiškinys vadinamas nepakartojamu skaitymu.
PAKARTOMAS SKAITYMAS — šiame izoliacijos lygyje neturime nepakartojamo nuskaitymo reiškinio dėl to, kad kiekvienai užklausai nuskaityti duomenis sukuriama momentinė rezultato duomenų nuotrauka, o kai pakartotinai panaudojama toje pačioje operacijoje, momentinės nuotraukos duomenys. yra naudojamas. Tačiau tokiu izoliacijos lygiu galima nuskaityti fantominius duomenis. Tai reiškia naujų eilučių, pridėtų lygiagrečiai atliktų operacijų, skaitymą.
SERIALIZUOJAMAS - aukščiausio lygio izoliacija. Jai būdinga tai, kad bet kokiu būdu sandoryje (skaitant ar keičiant) naudojami duomenys tampa prieinami kitoms operacijoms tik įvykdžius pirmą operaciją.
Pirmiausia išsiaiškinkime, ar operacijos operacijos yra atskirtos nuo pagrindinės gijos. Atidarykime 2 terminalo langus.
Kill ^t
Write ^t(1)
2
TSTART
Set ^t(1)=2Nėra izoliacijos. Viena gija mato, ką daro antrasis, atidaręs operaciją.
Pažiūrėkime, ar skirtingų gijų sandoriai mato, kas vyksta jų viduje.
Atidarykime 2 terminalo langus ir lygiagrečiai atidarykime 2 operacijas.
kill ^t
TSTART
Write ^t(1)
3
TSTART
Set ^t(1)=3
Lygiagrečios operacijos mato viena kitos duomenis. Taigi, gavome patį paprasčiausią, bet ir greičiausią izoliacijos lygį, READ UNCOMMITED.
Iš principo to būtų galima tikėtis iš pasaulinių šalių, kurių našumas visada buvo prioritetas.
Ką daryti, jei mums reikia didesnio izoliacijos lygio operacijose su globaliais?
Čia reikia pagalvoti, kam iš viso reikalingi izoliacijos lygiai ir kaip jie veikia.
Aukščiausias izoliacijos lygis SERIALIZE reiškia, kad lygiagrečiai vykdomų operacijų rezultatas yra lygiavertis jų nuosekliam vykdymui, o tai garantuoja susidūrimų nebuvimą.
Tai galime padaryti naudodami „ObjectScript“ išmaniuosius užraktus, kurie naudojami labai įvairiai: galite atlikti įprastą, laipsnišką, daugkartinį užrakinimą naudodami komandą .
Žemesni izoliacijos lygiai yra kompromisai, skirti padidinti duomenų bazės greitį.
Pažiūrėkime, kaip galime pasiekti skirtingus izoliacijos lygius naudodami spynas.
Šis operatorius leidžia paimti ne tik išskirtinius užraktus, reikalingus duomenims keisti, bet ir vadinamuosius bendruosius užraktus, kurie gali lygiagrečiai imtis kelių gijų, kai reikia nuskaityti duomenis, kurių skaitymo proceso metu neturėtų keisti kiti procesai.
Daugiau informacijos apie dviejų fazių blokavimo metodą rusų ir anglų kalbomis:
→
→
Sunkumas yra tas, kad operacijos metu duomenų bazės būsena gali būti nenuosekli, tačiau šie nenuoseklūs duomenys matomi kitiems procesams. Kaip to išvengti?
Naudodami užraktus sukursime matomumo langus, kuriuose duomenų bazės būsena bus nuosekli. O visas patekimas į tokius sutartos būklės matomumo langus bus kontroliuojamas spynomis.
Tų pačių duomenų bendrinamus užraktus galima naudoti pakartotinai – juos gali užtrukti keli procesai. Šie užraktai neleidžia kitiems procesams keisti duomenų, t.y. jie naudojami nuoseklios duomenų bazės būsenos langams formuoti.
Duomenų keitimui naudojami išskirtiniai užraktai – tokį užraktą gali užtrukti tik vienas procesas. Išskirtinę spyną gali pasiimti:
- Bet koks procesas, jei duomenys yra nemokami
- Tik procesas, kuris turi bendrinamą šių duomenų užraktą ir pirmasis pareikalavo išskirtinio užrakto.

Kuo siauresnis matomumo langas, tuo ilgiau kiti procesai jo turi laukti, tačiau tuo nuoseklesnė gali būti jame esančios duomenų bazės būsena.
READ_COMMITTED — šio lygio esmė ta, kad matome tik priskirtus duomenis iš kitų gijų. Jei kitos operacijos duomenys dar neįsipareigoti, matome jos senąją versiją.
Tai leidžia mums lygiagrečiai atlikti darbą, o ne laukti, kol užraktas bus atleistas.
Be ypatingų gudrybių senosios duomenų versijos IRIS nepamatysime, tad teks tenkintis su spynomis.
Atitinkamai, turėsime naudoti bendrinamus užraktus, kad duomenis būtų galima skaityti tik nuoseklumo momentais.
Tarkime, kad turime vartotojų bazę ^asmenis, kurie vienas kitam perveda pinigus.
Perkėlimo iš 123 asmens į 242 asmenį momentas:
LOCK +^person(123), +^person(242)
Set ^person(123, amount) = ^person(123, amount) - amount
Set ^person(242, amount) = ^person(242, amount) + amount
LOCK -^person(123), -^person(242)Pinigų sumos pareikalavimo iš asmens 123 momentas prieš nurašymą turi būti kartu su išskirtiniu bloku (pagal numatytuosius nustatymus):
LOCK +^person(123)
Write ^person(123)Ir jei jums reikia parodyti paskyros būseną savo asmeninėje paskyroje, galite naudoti bendrą užraktą arba jo visai nenaudoti:
LOCK +^person(123)#”S”
Write ^person(123)Tačiau jei darysime prielaidą, kad duomenų bazės operacijos atliekamos beveik akimirksniu (priminsiu, kad globalai yra daug žemesnio lygio struktūra nei reliacinė lentelė), tai šio lygio poreikis mažėja.
PAKARTOMAS SKAITYMAS – Šis izoliacijos lygis leidžia kelis kartus nuskaityti duomenis, kuriuos galima keisti vienu metu vykdant operacijas.
Atitinkamai turėsime užrakinti bendrai keičiamų duomenų skaitymą ir išskirtinius duomenų, kuriuos keičiame, užraktus.
Laimei, LOCK operatorius leidžia viename teiginyje detaliai išvardyti visas reikalingas spynas, kurių gali būti labai daug.
LOCK +^person(123, amount)#”S”
чтение ^person(123, amount)kitos operacijos (šiuo metu lygiagrečios gijos bando pakeisti ^person(123, suma), bet negali)
LOCK +^person(123, amount)
изменение ^person(123, amount)
LOCK -^person(123, amount)
чтение ^person(123, amount)
LOCK -^person(123, amount)#”S”Pateikiant užraktus, atskirtus kableliais, jie imami iš eilės, bet jei tai darote:
LOCK +(^person(123),^person(242))tada jie paimami atomiškai visi iš karto.
SERIALIZUOTI — turėsime nustatyti užraktus, kad galiausiai visos operacijos, turinčios bendrų duomenų, būtų vykdomos nuosekliai. Taikant šį metodą, dauguma spynų turėtų būti išskirtinės ir pritaikytos mažiausioms pasaulio vietoms.
Jei kalbame apie lėšų nurašymą globaliame ^asmenyje, tai jam priimtinas tik SERIALIZE izoliacijos lygis, nes pinigai turi būti leidžiami griežtai nuosekliai, kitaip tą pačią sumą galima išleisti kelis kartus.
4. Patvarumas
Aš atlikau bandymus su kietu konteinerio pjūviu
docker kill my-irisBazė juos gerai toleravo. Jokių problemų nenustatyta.
išvada
Pasauliniams klientams „InterSystems IRIS“ palaiko operacijų palaikymą. Jie tikrai atomiški ir patikimi. Norint užtikrinti duomenų bazės, pagrįstos globaliais, nuoseklumą, reikalingos programuotojo pastangos ir transakcijų naudojimas, nes joje nėra sudėtingų integruotų konstrukcijų, tokių kaip išoriniai raktai.
Globalių izoliacijos lygis nenaudojant spynų yra READ UNCOMMITED, o naudojant spynas galima užtikrinti iki SERIALIZE lygio.
Operacijų teisingumas ir greitis globaliuose labai priklauso nuo programuotojo įgūdžių: kuo plačiau naudojami skaitymo užraktai, tuo didesnis izoliacijos lygis, o kuo siauriau imami išskirtiniai užraktai, tuo greitesnis veikimas.
Šaltinis: www.habr.com
