Transakcije v globalih InterSystems IRIS

Transakcije v globalih InterSystems IRISInterSystems IRIS DBMS podpira zanimive strukture za shranjevanje podatkov – globale. V bistvu so to večnivojski ključi z različnimi dodatnimi dobrotami v obliki transakcij, hitrih funkcij za prečkanje podatkovnih dreves, ključavnic in lastnega jezika ObjectScript.

Preberite več o globalih v seriji člankov “Globali so zakladni meči za shranjevanje podatkov”:

Drevesa. 1. del
Drevesa. 2. del
Redki nizi. 3. del

Zanimalo me je, kako se transakcije izvajajo v globalih, kakšne funkcije obstajajo. Navsezadnje je to popolnoma drugačna struktura za shranjevanje podatkov kot običajne tabele. Veliko nižji nivo.

Kot je znano iz teorije relacijskih baz podatkov, mora dobra izvedba transakcij zadostiti zahtevam KISLINA:

A - Atomsko (atomskost). Zabeležijo se vse spremembe v transakciji ali sploh nobena.

C - Doslednost. Po zaključku transakcije mora biti logično stanje baze podatkov interno skladno. V mnogih pogledih ta zahteva zadeva programerja, vendar v primeru baz podatkov SQL zadeva tudi tuje ključe.

Jaz - Izola. Transakcije, ki potekajo vzporedno, ne smejo vplivati ​​druga na drugo.

D - Vzdržljiv. Po uspešnem zaključku transakcije težave na nižjih ravneh (na primer izpad električne energije) ne bi smele vplivati ​​na podatke, spremenjene s transakcijo.

Globali so nerelacijske podatkovne strukture. Zasnovani so tako, da delujejo zelo hitro na zelo omejeni strojni opremi. Oglejmo si izvedbo transakcij v globalih z uporabo uradna slika dockerja IRIS.

Za podporo transakcij v IRIS se uporabljajo naslednji ukazi: TSTART, TCOMMIT, TROLLACK.

1. Atomičnost

Najlažji način za preverjanje je atomičnost. Preverjamo iz konzole baze podatkov.

Kill ^a
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
TCOMMIT

Potem sklepamo:

Write ^a(1), “ ”, ^a(2), “ ”, ^a(3)

Dobimo:

1 2 3

Vse je vredu. Atomičnost se ohranja: vse spremembe se zabeležijo.

Zapletimo nalogo, vnesemo napako in vidimo, kako je transakcija shranjena, delno ali sploh ne.

Ponovno preverimo atomičnost:

Kill ^A
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3

Nato bomo kontejner na silo ustavili, ga izstrelili in videli.

docker kill my-iris

Ta ukaz je skoraj enakovreden prisilni zaustavitvi, saj pošlje signal SIGKILL za takojšnjo zaustavitev procesa.

Mogoče je bila transakcija delno shranjena?

WRITE ^a(1), ^a(2), ^a(3)
^
<UNDEFINED> ^a(1)

- Ne, ni se ohranilo.

Poskusimo ukaz za povrnitev nazaj:

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)

Tudi ohranjeno ni nič.

2. Doslednost

Ker so v bazah podatkov, ki temeljijo na globalih, tudi ključi izdelani na globalih (naj vas spomnim, da je global struktura nižjega nivoja za shranjevanje podatkov kot relacijske tabele), je za izpolnjevanje zahteve skladnosti treba vključiti spremembo ključa v isti transakciji kot sprememba v globalu.

Imamo na primer globalno ^person, v katero shranjujemo osebnosti in kot ključ uporabljamo TIN.

^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
...

Za hitro iskanje po priimku in imenu smo naredili ključ ^index.

^index(‘Kamenev’, ‘Sergey’, 1234567) = 1

Da bo baza podatkov skladna, moramo osebo dodati takole:

TSTART
^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
^index(‘Kamenev’, ‘Sergey’, 1234567) = 1
TCOMMIT

Skladno s tem moramo pri brisanju uporabiti tudi transakcijo:

TSTART
Kill ^person(1234567)
ZKill ^index(‘Kamenev’, ‘Sergey’, 1234567)
TCOMMIT

Z drugimi besedami, izpolnjevanje zahteve skladnosti je v celoti na plečih programerja. Toda ko gre za globale, je to normalno zaradi njihove narave na nizki ravni.

3. Izolacija

Tukaj se začne divjina. Številni uporabniki hkrati delajo na isti bazi podatkov in spreminjajo iste podatke.

Situacija je primerljiva s tem, ko veliko uporabnikov hkrati dela z istim repozitorijem kode in poskuša hkrati potrditi spremembe v več datotekah hkrati.

Podatkovna baza bi morala vse urediti v realnem času. Glede na to, da v resnih podjetjih obstaja celo posebna oseba, ki skrbi za nadzor različic (za združevanje vej, reševanje konfliktov ipd.), baza pa mora vse to početi v realnem času, je zahtevnost naloge in pravilnost oblikovanje podatkovne baze in koda, ki ji služi.

Baza podatkov ne more razumeti pomena dejanj, ki jih izvajajo uporabniki, da bi se izognili konfliktom, če delajo na istih podatkih. Lahko razveljavi samo eno transakcijo, ki je v nasprotju z drugo, ali pa ju izvede zaporedno.

Druga težava je, da je lahko med izvajanjem transakcije (pred potrditvijo) stanje baze nekonsistentno, zato je zaželeno, da druge transakcije nimajo dostopa do nekonsistentnega stanja baze, kar se doseže v relacijskih bazah podatkov. na več načinov: ustvarjanje posnetkov, vrstic z več različicami itd.

Pri vzporednem izvajanju transakcij nam je pomembno, da se medsebojno ne motijo. To je lastnost izolacije.

SQL definira 4 ravni izolacije:

  • PREBERITE NEPOROČENO
  • PREBERENO ZAVEZANO
  • PONOVLJIVO BRANJE
  • SERIJSKO PRIZN

Oglejmo si vsako raven posebej. Stroški izvajanja vsake stopnje rastejo skoraj eksponentno.

PREBERITE NEPOROČENO - to je najnižja stopnja izolacije, a hkrati najhitrejša. Transakcije lahko berejo medsebojne spremembe.

PREBERENO ZAVEZANO je naslednja stopnja izolacije, ki je kompromis. Transakcije ne morejo prebrati sprememb druga druge pred potrditvijo, lahko pa preberejo vse spremembe, narejene po potrditvi.

Če imamo dolgo transakcijo T1, med katero so se zgodili komiti v transakcijah T2, T3 ... Tn, ki so delale z istimi podatki kot T1, potem bomo pri zahtevi po podatkih v T1 vsakič dobili drugačen rezultat. Ta pojav imenujemo neponovljivo branje.

PONOVLJIVO BRANJE — na tej ravni izolacije nimamo pojava neponovljivega branja, ker se za vsako zahtevo za branje podatkov ustvari posnetek rezultatov podatkov in ob ponovni uporabi v isti transakciji se podatki iz posnetka se uporablja. Vendar pa je na tej ravni izolacije mogoče brati fantomske podatke. To se nanaša na branje novih vrstic, ki so bile dodane z vzporedno odobrenimi transakcijami.

SERIJSKO PRIZN — najvišja stopnja izolacije. Zanj je značilno, da podatki, ki so kakorkoli uporabljeni v transakciji (branje ali spreminjanje), postanejo na voljo drugim transakcijam šele po zaključku prve transakcije.

Najprej ugotovimo, ali obstaja izolacija operacij v transakciji od glavne niti. Odprimo 2 okni terminala.

Kill ^t

Write ^t(1)
2

TSTART
Set ^t(1)=2

Ni izolacije. Ena nit vidi, kaj počne druga, ki je odprla transakcijo.

Poglejmo, ali transakcije različnih niti vidijo, kaj se dogaja v njih.

Odprimo 2 okni terminala in odprimo 2 transakciji vzporedno.

kill ^t
TSTART
Write ^t(1)
3

TSTART
Set ^t(1)=3

Vzporedne transakcije vidijo podatke druga druge. Dobili smo torej najpreprostejšo, a tudi najhitrejšo stopnjo izolacije, READ UNCOMMITED.

To bi načeloma lahko pričakovali pri globalcih, pri katerih je bila zmogljivost vedno na prvem mestu.

Kaj pa, če potrebujemo višjo stopnjo izolacije pri operacijah na globalih?

Tukaj morate razmisliti, zakaj so stopnje izolacije sploh potrebne in kako delujejo.

Najvišja stopnja izolacije, SERIALIZE, pomeni, da je rezultat transakcij, ki se izvajajo vzporedno, enakovreden njihovemu zaporednemu izvajanju, kar zagotavlja odsotnost kolizij.

To lahko naredimo s pametnimi ključavnicami v ObjectScriptu, ki imajo veliko različnih uporab: z ukazom lahko naredite običajno, inkrementalno, večkratno zaklepanje LOCK.

Nižje ravni izolacije so kompromisi, namenjeni povečanju hitrosti baze podatkov.

Poglejmo, kako lahko z uporabo ključavnic dosežemo različne stopnje izolacije.

Ta operater vam omogoča, da sprejmete ne samo izključna zaklepanja, potrebna za spreminjanje podatkov, ampak tudi tako imenovana skupna zaklepanja, ki lahko sprejmejo več niti vzporedno, ko morajo prebrati podatke, ki jih drugi procesi med postopkom branja ne smejo spreminjati.

Več informacij o metodi dvofaznega blokiranja v ruskem in angleškem jeziku:

Dvofazna blokada
Dvofazno zaklepanje

Težava je v tem, da je med transakcijo stanje baze podatkov lahko nedosledno, vendar so ti nekonsistentni podatki vidni drugim procesom. Kako se temu izogniti?

S ključavnicami bomo ustvarili vidna okna, v katerih bo stanje baze podatkov konsistentno. In vsi dostopi do takšnih oken vidnosti dogovorjenega stanja bodo nadzorovani s ključavnicami.

Zaklepanja v skupni rabi za iste podatke je mogoče ponovno uporabiti – sprejme jih lahko več procesov. Te ključavnice preprečujejo drugim procesom spreminjanje podatkov, tj. uporabljajo se za oblikovanje oken doslednega stanja baze podatkov.

Ekskluzivne ključavnice se uporabljajo za spremembe podatkov - samo en proces lahko prevzame takšno ključavnico. Ekskluzivno ključavnico lahko prevzame:

  1. Vsak proces, če so podatki brezplačni
  2. Samo proces, ki ima skupno zaklepanje teh podatkov in je prvi zahteval izključno zaklepanje.

Transakcije v globalih InterSystems IRIS

Čim ožje je okno vidnosti, tem dlje morajo drugi procesi čakati nanj, a bolj dosledno je lahko stanje baze podatkov v njej.

READ_COMMITTED — bistvo te ravni je, da vidimo le odobrene podatke iz drugih niti. Če podatki v drugi transakciji še niso bili odobreni, potem vidimo njihovo staro različico.

To nam omogoča vzporedno delo, namesto da čakamo na sprostitev ključavnice.

Brez posebnih trikov stare različice podatkov v IRIS ne bomo mogli videti, zato se bomo morali zadovoljiti s ključavnicami.

V skladu s tem bomo morali uporabiti skupne ključavnice, da omogočimo branje podatkov le v trenutkih doslednosti.

Recimo, da imamo bazo uporabnikov ^osebe, ki drug drugemu nakazujejo denar.

Trenutek prestopa z osebe 123 na osebo 242:

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)

Trenutek zahtevanja zneska denarja od osebe 123 pred bremenitvijo mora spremljati izključni blok (privzeto):

LOCK +^person(123)
Write ^person(123)

In če morate v osebnem računu prikazati stanje računa, lahko uporabite skupno ključavnico ali je sploh ne uporabite:

LOCK +^person(123)#”S”
Write ^person(123)

Vendar, če predpostavimo, da se operacije baze podatkov izvajajo skoraj v trenutku (naj vas spomnim, da so globali struktura veliko nižje ravni kot relacijske tabele), potem se potreba po tej ravni zmanjša.

PONOVLJIVO BRANJE - Ta raven izolacije omogoča večkratno branje podatkov, ki jih je mogoče spremeniti s sočasnimi transakcijami.

V skladu s tem bomo morali postaviti skupno zaklepanje za branje podatkov, ki jih spreminjamo, in izključno zaklepanje podatkov, ki jih spreminjamo.

Na srečo vam operater LOCK omogoča, da v enem stavku podrobno navedete vse potrebne ključavnice, ki jih je lahko veliko.

LOCK +^person(123, amount)#”S”
чтение ^person(123, amount)

druge operacije (trenutno vzporedne niti poskušajo spremeniti ^person(123, znesek), vendar ne morejo)

LOCK +^person(123, amount)
изменение ^person(123, amount)
LOCK -^person(123, amount)

чтение ^person(123, amount)
LOCK -^person(123, amount)#”S”

Pri navajanju ključavnic, ločenih z vejicami, se upoštevajo zaporedno, če pa naredite to:

LOCK +(^person(123),^person(242))

potem se vzamejo atomsko vse naenkrat.

SERIJALIZIRANJE — morali bomo nastaviti zaklepe, tako da se na koncu vse transakcije, ki imajo skupne podatke, izvajajo zaporedno. Pri tem pristopu mora biti večina zaklepanja izključnih in sprejetih na najmanjših področjih globalnega delovanja.

Če govorimo o bremenitvi sredstev v globalni osebi ^, potem je zanjo sprejemljiva le stopnja izolacije SERIALIZE, saj je treba denar porabiti strogo zaporedno, sicer je mogoče isti znesek porabiti večkrat.

4. Trajnost

Opravil sem teste s trdim rezanjem posode z uporabo

docker kill my-iris

Podlaga jih je dobro prenašala. Težave niso bile ugotovljene.

Zaključek

Za globalno ima InterSystems IRIS podporo za transakcije. So resnično atomski in zanesljivi. Da bi zagotovili konsistentnost baze podatkov, ki temelji na globalih, so potrebni programerski napori in uporaba transakcij, saj nima zapletenih vgrajenih konstruktov, kot so tuji ključi.

Raven izolacije globalov brez uporabe ključavnic je READ UNCOMMITED, pri uporabi ključavnic pa jo je mogoče zagotoviti do ravni SERIALIZE.

Pravilnost in hitrost transakcij na globalih sta zelo odvisni od spretnosti programerja: bolj ko se pri branju uporabljajo zaklepanja v širši skupni rabi, višja je stopnja izolacije in več kot je ožje izključujočih zaklepanj, hitrejša je zmogljivost.

Vir: www.habr.com

Dodaj komentar