InterSystems IRIS DBMS tukee mielenkiintoisia rakenteita tietojen tallentamiseen - globaaleja. Pohjimmiltaan nämä ovat monitasoisia avaimia, joissa on erilaisia lisähyötyjä tapahtumien muodossa, nopeita toimintoja datapuiden läpikulkuun, lukot ja oma ObjectScript-kieli.
Lue lisää globaaleista artikkelisarjasta "Globalit ovat aarremiekkoja tietojen tallentamiseen":
Kiinnostuin siitä, miten transaktiot toteutetaan globaaleilla, mitä ominaisuuksia siellä on. Loppujen lopuksi tämä on täysin erilainen tietojen tallennusrakenne kuin tavalliset taulukot. Paljon matalampi taso.
Kuten relaatiotietokantojen teoriasta tiedetään, transaktioiden hyvän toteutuksen tulee täyttää vaatimukset
A - Atomi (atomisiteetti). Kaikki tapahtumaan tehdyt muutokset tai ei mitään muutoksia kirjataan.
C - Johdonmukaisuus. Kun tapahtuma on valmis, tietokannan loogisen tilan on oltava sisäisesti johdonmukainen. Tämä vaatimus koskee monella tapaa ohjelmoijaa, mutta SQL-tietokantojen tapauksessa myös vierasavaimia.
I - Eristä. Rinnakkaiset tapahtumat eivät saa vaikuttaa toisiinsa.
D - Kestävä. Tapahtuman onnistuneen loppuun saattamisen jälkeen alemmilla tasoilla esiintyvien ongelmien (esimerkiksi sähkökatkos) ei pitäisi vaikuttaa tapahtuman muuttamiin tietoihin.
Globaalit ovat ei-relaatiotietorakenteita. Ne on suunniteltu toimimaan erittäin nopeasti erittäin rajoitetuilla laitteistoilla. Katsotaanpa transaktioiden toteutusta globaaleissa käyttäen
IRIS-tapahtumien tukemiseen käytetään seuraavia komentoja:
1. Atomuus
Helpoin tapa tarkistaa on atomiteetti. Tarkistamme tietokantakonsolista.
Kill ^a
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
TCOMMIT
Sitten päätämme:
Write ^a(1), “ ”, ^a(2), “ ”, ^a(3)
Saamme:
1 2 3
Kaikki on hyvin. Atomisuus säilyy: kaikki muutokset kirjataan.
Monimutkaistaan tehtävää, esitellään virhe ja katsotaan kuinka tapahtuma tallennetaan, osittain tai ei ollenkaan.
Tarkistetaan vielä atomiteetti:
Kill ^A
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
Sitten pysäytämme kontin väkisin, käynnistämme sen ja katsomme.
docker kill my-iris
Tämä komento vastaa lähes pakotettua sammutusta, koska se lähettää SIGKILL-signaalin pysäyttääkseen prosessin välittömästi.
Ehkä kauppa säästyi osittain?
WRITE ^a(1), ^a(2), ^a(3)
^
<UNDEFINED> ^a(1)
- Ei, se ei ole säilynyt.
Kokeillaan palautuskomentoa:
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)
Mikään ei myöskään ole säilynyt.
2. Johdonmukaisuus
Koska globaleihin perustuvissa tietokannoissa avaimet tehdään myös globaaleille (muistutan, että globaali on alemman tason rakenne tietojen tallentamiseen kuin relaatiotaulukko), johdonmukaisuusvaatimuksen täyttämiseksi avaimeen tulee tehdä muutos. samassa liiketoimessa kuin muutos globaalissa.
Meillä on esimerkiksi globaali ^henkilö, johon tallennamme henkilöitä ja käytämme TIN-tunnusta avaimena.
^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
...
Tehdäksemme nopean haun suku- ja etunimen perusteella, teimme ^index-näppäimen.
^index(‘Kamenev’, ‘Sergey’, 1234567) = 1
Jotta tietokanta olisi johdonmukainen, meidän on lisättävä henkilö seuraavasti:
TSTART
^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
^index(‘Kamenev’, ‘Sergey’, 1234567) = 1
TCOMMIT
Vastaavasti, kun poistamme, meidän on käytettävä myös tapahtumaa:
TSTART
Kill ^person(1234567)
ZKill ^index(‘Kamenev’, ‘Sergey’, 1234567)
TCOMMIT
Toisin sanoen johdonmukaisuusvaatimuksen täyttäminen on täysin ohjelmoijan harteilla. Mutta mitä tulee globaaleihin, tämä on normaalia niiden matalan tason luonteen vuoksi.
3. Eristäminen
Tästä villit alkavat. Monet käyttäjät työskentelevät samanaikaisesti saman tietokannan parissa ja muuttavat samoja tietoja.
Tilanne on verrattavissa siihen, kun monet käyttäjät työskentelevät samanaikaisesti saman koodivaraston kanssa ja yrittävät samanaikaisesti tehdä muutoksia useisiin tiedostoihin kerralla.
Tietokannan pitäisi selvittää kaikki reaaliajassa. Ottaen huomioon, että vakavissa yrityksissä on jopa erityinen henkilö, joka on vastuussa versionhallinnasta (haarojen yhdistämisestä, ristiriitojen ratkaisemisesta jne.), ja tietokannan on tehtävä tämä kaikki reaaliajassa, tehtävän monimutkaisuus ja oikeellisuus. tietokannan suunnittelu ja sitä palveleva koodi.
Tietokanta ei ymmärrä käyttäjien tekemien toimien merkitystä ristiriitojen välttämiseksi, jos he työskentelevät samojen tietojen parissa. Se voi kumota vain yhden tapahtuman, joka on ristiriidassa toisen kanssa, tai suorittaa ne peräkkäin.
Toinen ongelma on, että tapahtuman suorittamisen aikana (ennen sitoutumista) tietokannan tila voi olla epäjohdonmukainen, joten on toivottavaa, että muut tapahtumat eivät pääse käsiksi tietokannan epäjohdonmukaiseen tilaan, mikä saavutetaan relaatiotietokannoissa. monin tavoin: tilannekuvien luominen, rivien moniversio jne.
Rinnakkaisten tapahtumien suorittamisessa on meille tärkeää, etteivät ne häiritse toisiaan. Tämä on eristäytymisen ominaisuus.
SQL määrittelee 4 eristystasoa:
- LUE SITOUMATTOMASTI
- LUE SITOUTUNUT
- TOISTETTU LUE
- SARJOITTAVA
Katsotaanpa jokaista tasoa erikseen. Kunkin tason toteutuskustannukset kasvavat lähes eksponentiaalisesti.
LUE SITOUMATTOMASTI - Tämä on alhaisin eristyksen taso, mutta samalla nopein. Tapahtumat voivat lukea toistensa tekemiä muutoksia.
LUE SITOUTUNUT on eristyksen seuraava taso, mikä on kompromissi. Tapahtumat eivät voi lukea toistensa muutoksia ennen sitoumusta, mutta ne voivat lukea sitoumuksen jälkeen tehdyt muutokset.
Jos meillä on pitkä tapahtuma T1, jonka aikana tapahtui sitoumuksia tapahtumissa T2, T3 ... Tn, jotka toimivat samoilla tiedoilla kuin T1, niin T1:ssä dataa pyydettäessä saadaan joka kerta eri tulos. Tätä ilmiötä kutsutaan ei-toistettavaksi lukemiseksi.
TOISTETTU LUE – tällä eristystasolla meillä ei ole ei-toistettavan lukemisen ilmiötä, koska jokaista tietojen lukupyyntöä varten luodaan tilannekuva tulostiedoista ja kun niitä käytetään uudelleen samassa tapahtumassa, tilannevedoksen tiedot käytetään. Phantom-dataa on kuitenkin mahdollista lukea tällä eristystasolla. Tämä viittaa uusien rivien lukemiseen, jotka on lisätty rinnakkaisilla sitoutuneilla tapahtumilla.
SARJOITTAVA — korkein eristystaso. Sille on ominaista se, että tapahtumassa millään tavalla käytetyt tiedot (lukeminen tai muuttaminen) tulevat muiden tapahtumien saataville vasta ensimmäisen tapahtuman suorittamisen jälkeen.
Selvitetään ensin, onko tapahtumassa toimintojen eristäminen pääsäikeestä. Avataan 2 pääteikkunaa.
Kill ^t
Write ^t(1)
2
TSTART
Set ^t(1)=2
Eristystä ei ole. Yksi säie näkee, mitä toinen tapahtuman avannut tekee.
Katsotaanpa, näkevätkö eri säikeiden tapahtumat, mitä niiden sisällä tapahtuu.
Avataan 2 pääteikkunaa ja 2 tapahtumaa rinnakkain.
kill ^t
TSTART
Write ^t(1)
3
TSTART
Set ^t(1)=3
Rinnakkaiset tapahtumat näkevät toistensa tiedot. Saimme siis yksinkertaisimman, mutta myös nopeimman eristystason, READ UN COMMITED.
Periaatteessa tätä voitaisiin odottaa globaaleilta tahoilta, joille suorituskyky on aina ollut prioriteetti.
Entä jos tarvitsemme korkeamman tason eristäytymistä globaaleilla toimissa?
Täällä sinun on pohdittava, miksi eristystasoja ylipäänsä tarvitaan ja miten ne toimivat.
Korkein eristystaso, SERIALIZE, tarkoittaa, että rinnakkain suoritettujen tapahtumien tulos vastaa niiden peräkkäistä toteutusta, mikä takaa yhteentörmäysten puuttumisen.
Voimme tehdä tämän käyttämällä ObjectScriptin älykkäitä lukkoja, joilla on paljon erilaisia käyttötarkoituksia: voit tehdä säännöllisen, inkrementaalisen, usean lukituksen komennolla
Alemmat eristystasot ovat kompromisseja, jotka on suunniteltu lisäämään tietokannan nopeutta.
Katsotaanpa, kuinka voimme saavuttaa erilaisia eristystasoja lukkojen avulla.
Tämän operaattorin avulla voit ottaa paitsi eksklusiivisia lukkoja, joita tarvitaan tietojen vaihtamiseen, myös niin kutsuttuja jaettuja lukoja, jotka voivat viedä useita säikeitä rinnakkain, kun niiden on luettava tietoja, joita muiden prosessien ei pitäisi muuttaa lukuprosessin aikana.
Lisätietoja kaksivaiheisesta estomenetelmästä venäjäksi ja englanniksi:
→
→
Vaikeus on, että tapahtuman aikana tietokannan tila voi olla epäjohdonmukainen, mutta tämä epäjohdonmukainen data näkyy muille prosesseille. Kuinka välttää tämä?
Luomme lukkojen avulla näkyvyysikkunoita, joissa tietokannan tila on johdonmukainen. Ja kaikkea pääsyä sellaisiin sovitun tilan näkyvyysikkunoihin valvotaan lukoilla.
Samojen tietojen jaetut lukot ovat uudelleenkäytettäviä – useat prosessit voivat viedä ne. Nämä lukot estävät muita prosesseja muuttamasta tietoja, esim. niitä käytetään muodostamaan johdonmukaisia tietokantatilan ikkunoita.
Tietojen muuttamiseen käytetään eksklusiivisia lukkoja - vain yksi prosessi voi kestää tällaisen lukon. Ainutlaatuisen lukon voi ottaa:
- Mikä tahansa prosessi, jos tiedot ovat ilmaisia
- Vain prosessi, jolla on jaettu lukko näille tiedoille ja joka pyysi ensimmäisenä yksinomaista lukitusta.
Mitä kapeampi näkyvyysikkuna on, sitä kauemmin muiden prosessien on odotettava sitä, mutta sitä johdonmukaisempi tietokannan tila siinä voi olla.
READ_COMMITTED - Tämän tason ydin on, että näemme vain sitoutuneita tietoja muista säikeistä. Jos toisen tapahtuman tietoja ei ole vielä sitoutunut, näemme sen vanhan version.
Näin voimme rinnastaa työn sen sijaan, että odotamme lukon vapautumista.
Ilman erikoistemppuja emme voi nähdä IRIS:ssä tiedoista vanhaa versiota, joten joudumme tyytymään lukoihin.
Tästä syystä meidän on käytettävä jaettuja lukkoja, jotta tiedot voidaan lukea vain johdonmukaisina hetkinä.
Oletetaan, että meillä on käyttäjäkunta ^henkilö, joka siirtää rahaa toisilleen.
Siirtymähetki henkilöltä 123 henkilölle 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)
Rahasumman pyytämiseen henkilöltä 123 ennen veloitusta on liitettävä eksklusiivinen lohko (oletuksena):
LOCK +^person(123)
Write ^person(123)
Ja jos sinun on näytettävä tilin tila henkilökohtaisella tililläsi, voit käyttää jaettua lukkoa tai olla käyttämättä sitä ollenkaan:
LOCK +^person(123)#”S”
Write ^person(123)
Jos kuitenkin oletetaan, että tietokantatoiminnot suoritetaan lähes välittömästi (muistutan, että globaalit ovat paljon alemman tason rakenne kuin relaatiotaulukko), tämän tason tarve vähenee.
TOISTETTU LUE - Tämä eristystaso mahdollistaa useiden tietojen lukemisen, joita voidaan muokata samanaikaisilla tapahtumilla.
Näin ollen meidän on asetettava jaettu lukitus muuttamiemme tietojen lukemiselle ja eksklusiiviset lukot muumille tiedoille.
Onneksi LOCK-operaattorin avulla voit listata yksityiskohtaisesti kaikki tarvittavat lukot, joita voi olla paljon, yhdellä lauseella.
LOCK +^person(123, amount)#”S”
чтение ^person(123, amount)
muut toiminnot (tällä hetkellä rinnakkaiset säikeet yrittävät muuttaa ^henkilö(123, summa), mutta eivät voi)
LOCK +^person(123, amount)
изменение ^person(123, amount)
LOCK -^person(123, amount)
чтение ^person(123, amount)
LOCK -^person(123, amount)#”S”
Kun luettelet lukot pilkuilla erotettuina, ne otetaan peräkkäin, mutta jos teet näin:
LOCK +(^person(123),^person(242))
sitten ne otetaan atomisesti kaikki kerralla.
SARJALLISTAA — Meidän on asetettava lukot niin, että lopulta kaikki yhteistä dataa sisältävät tapahtumat suoritetaan peräkkäin. Tätä lähestymistapaa käytettäessä useimpien lukkojen tulisi olla yksinoikeudellisia, ja ne on suoritettava maailman pienimmillä alueilla.
Jos puhumme varojen veloituksesta globaalissa ^henkilössä, niin vain SERIALIZE-eristystaso on sille hyväksyttävä, koska rahat on käytettävä tiukasti peräkkäin, muuten on mahdollista kuluttaa sama määrä useita kertoja.
4. Kestävyys
Tein testejä säiliön kovaa leikkaamista käyttäen
docker kill my-iris
Pohja kesti niitä hyvin. Mitään ongelmia ei havaittu.
Johtopäätös
InterSystems IRIS tarjoaa maailmanlaajuisille tapahtumille tukea. Ne ovat todella atomisia ja luotettavia. Globaaleihin perustuvan tietokannan johdonmukaisuuden varmistamiseksi tarvitaan ohjelmoijien ponnisteluja ja tapahtumien käyttöä, koska siinä ei ole monimutkaisia sisäänrakennettuja rakenteita, kuten vierasavaimia.
Globaalien eristystaso ilman lukkoja on READ UNCOMMITED, ja lukkoja käytettäessä se voidaan varmistaa SERIALIZE-tasoon asti.
Globaalien tapahtumien oikeellisuus ja nopeus riippuvat suuresti ohjelmoijan taidosta: mitä laajemmin jaettuja lukkoja käytetään lukemisessa, sitä korkeampi eristysaste ja mitä suppeammin poissulkevat lukot otetaan, sitä nopeampi suorituskyky.
Lähde: will.com