Tehingud InterSystems IRIS globaalides

Tehingud InterSystems IRIS globaalidesAndmebaasi InterSystems IRIS toetab huvitavaid andmestruktuure - globaalid. Tegelikult on need mitmetasandilised vÔtmed, millel on erinevad lisafunktsioonid, nagu tehingud, kiire funktsionaalsus andmepuude lÀbimiseks, lukustused ja oma keele ObjectScript.

Rohkem globaalsest sĂŒgiseks artiklite tsĂŒklis „Globaalid - andmete salvestamise mÔÔgad”:

Puud. Osa 1
Puud. Osa 2
Sparssed massiivid. Osa 3

Mind huvitab, kuidas tehingud globaalides on ellu viidud, millised omadused seal on. See on ju tÀiesti erinev andmestruktuur vÔrreldes traditsiooniliste tabelitega. Oluliselt madalamal tasemel.

Kuna on teada, et relatsiooniliste andmebaaside teooriast peaks hea tehingu teostus vastama nÔuetele ACID:

A - Atoomilisus. Kogu tehingu jooksul tehtud muudatused peavad olema kas tÀiesti salvestatud vÔi mitte midagi.

C - Konsistentsus. Tehingu lÔpuks peab andmebaasi loogiline seisund olema omavahel kooskÔlas. Suur osa sellest nÔudest puudutab programmeerijat, kuid SQL-andmebaaside puhul kehtib see ka vÀliste vÔtmete kohta.

I - Isolatsioon. Samal ajal toimuvad tehingud ei tohiks ĂŒksteist mĂ”jutada.

D - Vastupidavus. PÀrast tehingu edukat lÔpetamist ei tohiks madalama taseme probleemid (nt voolukatkestus) mÔjutada tehingu kÀigus muudetud andmeid.

Globaalid on relatsioonilised andmestruktuurid. Need loodi ĂŒlikiireks tööks vĂ€ga piiratud riistvaral. Uurime, kuidas tehingud globaalides on ellu viidud ametliku docker-pildi IRIS abil.

Tehingute toetamiseks IRIS-is kasutatakse jÀrgmisi kÀske: TSTART, TCOMMIT, TROLLBACK.

1. Atoomilisus

Atoomilisust on kÔige lihtsam kontrollida. Kontrollime andmebaasi konsoolist.

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

SeejÀrel teeme jÀrelduse:

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

Saame:

1 2 3

KÔik on korras. Atoomilisus on tagatud: kÔik muudatused on salvestatud.

VĂ”tame ĂŒlesande keerulisemaks, sisse viies vea, ja vaatame, kuidas tehing sĂ€ilib, osaliselt vĂ”i ĂŒldse mitte.

Kordame atooblisuse kontrolli:

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

PÀrast seda peatame konteineri sunniviisil, kÀivitame selle uuesti ja vaatame.

docker kill my-iris

See kÀsk on praktiliselt ekvivalentne jÀrsu voolu katkestamisega, kuna see saadab protsessile SIGKILL kohese peatumise signaali.

Kas tehing vÔib olla osaliselt salvestatud?

WRITE ^a(1), ^a(2), ^a(3)
^
 ^a(1)

— Ei, ei salvestunud.

Proovime tagasipöördumise kÀsku:

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

WRITE ^a(1), ^a(2), ^a(3)
^
 ^a(1)

Samuti ei salvestunud midagi.

2. Ühtsus

Kuna globaalides luuakse vĂ”tmed samuti globaalide jĂ€rgi (tuletan meelde, et gloobaal on madalama taseme struktuur andmete salvestamiseks kui relatsiooniline tabel), peab ĂŒhtsuse nĂ”ude tĂ€itmiseks vĂ”tme muutmine olema sama tehingu sees nagu gloobala muutmine.

NÀiteks meil on gloobaal ^person, kus salvestame isikute andmeid ja vÔtmena kasutame isikukoodi.

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

Kuna kiireks otsinguks perekonna nime ja eesnime jÀrgi, lÔime vÔtme ^index.

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

Selleks, et andmebaas oleks ĂŒhtne, peame isikuandmeid lisama jĂ€rgmiselt:

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

Seega, kustutamise korral peame samuti kasutama tehingut:

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

TeisisĂ”nu, ĂŒhtsuse nĂ”uete tĂ€itmine lasub tĂ€ielikult programmeerija Ă”lul. Kuid kui me rÀÀgime globaalidest, on see normaalne, kuna nende madalama taseme loomus.

3. Isolatsioon

Siin hakkavad keerulised asjad pihta. Paljud kasutajad töötavad sama andmebaasi kallal samal ajal, muutes samu andmeid.

Situatsioon on vĂ”rreldav sellega, kui palju kasutajaid ĂŒritab samaaegselt töötada ĂŒhe ja sama koodi hoidla kallal ning ĂŒritavad korraga teha komiteeringuid paljude failide osas.

Andmebaas peab seda kĂ”ike lahendama reaalajas. Arvestades, et tĂ”sistes ettevĂ”tetes on isegi spetsiaalne isik, kes vastutab versioonihalduse eest (harude ĂŒhinemine, konfliktide lahendamine jne), ja andmebaas peab seda kĂ”ike tegema reaalajas, siis tekib selge ĂŒlesande keerukus ning andmebaasi ja sellele teenindava koodi Ă”ige projekteerimise vajadus.

Andmebaas ei saa mĂ”ista, mida kasutajad teevad, et vĂ€ltida konflikte, kui nad töötavad sama teabega. See suudab ainult tĂŒhistada ĂŒhe tehingu, mis on vasturÀÀkiv teisele, vĂ”i tĂ€ita need jĂ€rjestikku.

Veel ĂŒks probleem on see, et tehingu tĂ€itmise ajal (enne kinnitamist) vĂ”ib andmebaasi seisund olla ĂŒhitamatu, seetĂ”ttu on soovitav, et teised tehingud ei pÀÀseks ĂŒhitamata andmebaasi olekusse. Rikkalikud andmebaasid saavutavad selle mitmel viisil: lĂ”ike loomise, versioonide haldamise jne kaudu.

Tehingute paralleelsel tĂ€itmisel on oluline, et need ei segaks ĂŒksteist. See on isoleerituse omadus.

SQL mÀÀratleb 4 isoleerituse taset:

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE

Vaadakem iga taset eraldi. Iga taseme rakendamise kulud kasvavad peaaegu eksponentsiaalselt.

READ UNCOMMITTED — see on madalaim isoleerituse tase, kuid samal ajal ka kiireim. Tehingud saavad lugeda ĂŒksteise tehtud muudatusi.

READ COMMITTED — see on jĂ€rgmine isoleerituse tase, mis on kompromiss. Tehingud ei saa lugeda ĂŒksteise tehtud muudatusi enne kinnitamist, kuid saavad lugeda kĂ”iki muudatusi, mis on tehtud pĂ€rast kinnitamist.

Kui meil on pikk tehing T1, mille jooksul on toimunud kinnitamised tehingutes T2, T3 
 Tn, mis töötasid sama teabega nagu T1, siis T1-s andmeid kĂŒsides saame iga kord erineva tulemuse. Seda nĂ€htust nimetatakse mitteuuesti lugemiseks.

REPEATABLE READ — selle isoleerituse tasemega ei ole meil mitteuuesti lugemise nĂ€htust, kuna iga kord, kui andmeid loetakse, luuakse andmete tulemi lĂ”ige, ja selles sama tehingus kasutatakse andmeid lĂ”igetest. Kuid selle isoleerituse taseme korral on vĂ”imalik lugeda fantoomandmeid, mille alla kuuluvad uute ridade lugemine, mis on lisatud paralleelsete kinnitatud tehingute poolt.

SERIALIZABLE — kĂ”rgeim isoleerituse tase. Sellel on see omadus, et tehingus kasutatavad andmed (lugemiseks vĂ”i muutmiseks) muutuvad teistele tehingutele kĂ€ttesaadavaks alles pĂ€rast esimest tehingu lĂ”petamist.

Alustame sellest, kas tehingutes on toimingute isolatsioon peavoolust. Avame 2 terminali aken.

Kill ^t

Write ^t(1)
2

TSTART
Set ^t(1)=2

Isolatsiooni ei ole. Üks voog nĂ€eb, mida teeb teine, kes avas tehingu.

Vaadakem, kas erinevate voogude tehingud nÀevad, mis toimub nende sees.

Avame 2 terminali akent ja avame 2 tehingut paralleelselt.

kill ^t
TSTART
Write ^t(1)
3

TSTART
Set ^t(1)=3

Paralleelsed tehingud nĂ€evad ĂŒksteise andmeid. Niisiis saime kĂ”ige lihtsama, kuid ka kĂ”ige kiirema isolatsioonitase READ UNCOMMITED.

PÔhimÔtteliselt oli seda oodata globaalselt, kus tÔhusus oli alati esmatÀhtis.

Kuidas toimida, kui me vajame globaalsetes toimingutes kÔrgemat isolatsioonitaset?

Siin tasub mĂ”elda, miks ĂŒldse on vajalikud isolatsioonitasemed ja kuidas need toimivad.

KÔrgeim isolatsioonitase SERIALIZE tÀhendab, et paralleelselt teostatavate tehingute tulemus on ekvivalentne nende jÀrjestikusele teostamisele, mis tagab konflikti puudumise.

Seda saame teha, kasutades hÀsti planeeritud lukustusi ObjectScriptis, mis pakuvad mitmeid rakendusi: vÔime teha tavalise, inkrementaalse, mitmeotstarbelise lukustamise kÀsuga LOCK.

Madalamad isolatsioonitasemed on kompromissid, mille eesmÀrk on suurendada andmebaasi töökiirus.

Vaadakem, kuidas saame lukustuste abil saavutada erinevaid isolatsioonitasemeid.

See kÀsk vÔimaldab vÔtta mitte ainult eksklusiivseid lukustusi, mis on vajalikud andmete muutmiseks, vaid ka nn jagatud lukustusi, mida saavad korraga mitu voogu, kui nad peavad lugema andmeid, mida ei tohi teiste protsesside poolt lugemise ajal muuta.

Rohkem teavet kahefaasilise lukustamise meetodi kohta vene ja inglise keeles:

→ Kahefaasiline lukustus
→ Two-phase locking

Raskus seisneb selles, et tehingu ajal vÔib andmebaasi seisund olla konsolideerimata, kuid need konsolideerimata andmed on teistele protsessidele nÀhtavad. Kuidas seda vÀltida?

Loome lukustuste abil sellised vaateaknad, kus andmebaasi seisund on konsolideeritud. Ja kÔik sellistele konsolideeritud seisundi vaateakendele tehtavad pÀringud kontrollitakse lukustuste abil.

Jagatud lukud samaaegsetele andmetele on korduvkasutatavad - need vÔivad omada mitu protsessi. Need lukud keelavad teistel protsessidel andmete muutmist, st neid kasutatakse andmebaasi konsolideeritud oleku akende moodustamiseks.

Eksklusiivsed lukud on kasutusel andmete muutmiseks - sellist lukku saab omada ainult ĂŒks protsess. Eksklusiivset lukku saab vĂ”tta:

  1. Iga protsess, kui andmed on vabastatud
  2. Ainult see protsess, millel on nende andmete jagatud lukud ja kes esimesena soovis eksklusiivset lukku.

Tehingud InterSystems IRIS globaalides

Mida kitsam on nĂ€htavusaken, seda kauem peavad teised protsessid ootama, kuid seda ĂŒhtlasem vĂ”ib andmebaasi olek selles olla.

READ_COMMITTED — selle taseme sisu on, et nĂ€eme ainult teistest voogudest kinnitatud andmeid. Kui andmed teises tehingus ei ole veel kinnitatud, siis nĂ€eme nende vana versiooni.

See vÔimaldab meil tööd paralleliseerida, selle asemel et oodata luku vabastamist.

Ilma spetsiaalsete nÔtkusteta ei nÀe me vana andmeversiooni IRISes, seetÔttu peame rahulduma lukudega.

Seega peame jagatud lukudega lubama andmete lugemise ainult kooskÔlastusmomentide ajal.

Oletame, et meil on kasutajate andmebaas ^person, kes kannavad ĂŒksteisele raha.

RahaĂŒlekande hetk isikult 123 isikule 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)

Raha summa kĂŒsimise hetk isikult 123 enne arveldamist peab olema kaasas eksklusiivne lukustamine (vaikimisi):

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

Kui peab nĂ€itama konto seisu isiklikus kabinetis, siis saab kasutada jagatud lukku vĂ”i ĂŒldse mitte kasutada:

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

Kuid kui eeldada, et andmebaasi muudatuste teostamine toimub peaaegu koheselt (meenutan, et globaalid on palju madalamal tasemel struktuur kui suhteline tabel), siis on selle taseme vajadus vÀhenenud.

REPEATABLE READ — selle isolatsiooni tasemel on lubatud, et andmete lugemised, mida vĂ”ivad muuta paralleelsed tehingud, vĂ”ivad olla mitu.

Seega peame jagatud lukku panema andmete lugemiseks, mida me muudame ja eksklusiivsed lukud andmete jaoks, mida me muudame.

LOCK operaator vĂ”imaldab ĂŒhes operaatoris detailselt loetleda kĂ”ik vajalikud lukustused, mida vĂ”ib olla vĂ€ga palju.

LOCK +^person(123, amount)#”S”
loe ^person(123, amount)

muid operatsioone (sel ajal ĂŒritavad paralleelsed vood ^person(123, amount) muuta, kuid ei saa)

LOCK +^person(123, amount)
muuda ^person(123, amount)
LOCK -^person(123, amount)

loe ^person(123, amount)
LOCK -^person(123, amount)#”S”

Lukustuste loetlemisel koma kaudu vÔetakse neid jÀrjestikku, aga kui teha nii:

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

siis vÔetakse need atomaarsetena korraga.

SERIALIZE — me peame seadma lukustused nii, et lĂ”puks kĂ”ik tehingud, mis omavad ĂŒhiseid andmeid, teostatakse jĂ€rjestikku. Selle lĂ€henemise jaoks peavad enamik lukustustest olema eksklusiivsed ja vĂ”etud kĂ”ige vĂ€iksematel globaalsetel aladel, et tagada tulemuslikkus.

Kui rÀÀkida vahendite vÀljavÔtmisest globaalsetes ^person, siis on selle jaoks vastuvÔetav vaid SERIALIZE isolatsioonitase, kuna raha tuleb kulutada rangelt jÀrjestikku, vastasel juhul on vÔimalik kulutada sama summa mitu korda.

4. Kestus

Olen teinud katseid konteineri jĂ€rsu vĂ€ljalĂŒlitamisega

docker kill my-iris

Andmebaas talus seda hÀsti. Probleeme ei olnud.

KokkuvÔte

Globaalide jaoks InterSystems IRIS-is on tehingute tugi. Need on tÔeliselt atomaarsetes ja usaldusvÀÀrsetes. Andmebaasi jÀrjepidevuse tagamiseks globaalides on vajalik programmeerija pingutus ja tehingute kasutamine, kuna seal ei ole keerulisi sisseehitatud struktuure, nagu vÀlised vÔtmed.

Globaalide isolatsioonitase lukustuste kasutamata on READ UNCOMMITTED, aga lukustuste kasutamise korral vÔib selle tagada kuni SERIALIZE tasemeni.

Tehingute korrektne ja kiire toimimine globaalides sÔltub vÀga palju programmeerija oskustest: mida rohkem kasutatakse jagatud lukustusi lugemisel, seda kÔrgem on isolatsioonitase, ja mida kitsamalt vÔetakse eksklusiivseid lukustusi, seda rohkem suureneb jÔudlus.

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster