Transazzioni in InterSystems IRIS globals

Transazzioni in InterSystems IRIS globalsL'InterSystems IRIS DBMS supporta strutture interessanti per u almacenamentu di dati - globals. Essenzialmente, questi sò chjavi multi-livellu cù diversi boni supplementari in forma di transazzione, funzioni veloci per traversà l'arburi di dati, chjusi è a so propria lingua ObjectScript.

Leghjite più nantu à i global in a serie di articuli "Globali sò spade di tesoru per almacenà dati":

Arburi. Parte 1
Arburi. Parte 2
Arrays sparsi. Parte 3

Mi sò interessatu à cumu e transazzione sò implementate in globals, chì caratteristiche ci sò. Dopu tuttu, questu hè una struttura completamente diversa per almacenà dati da e tavule di solitu. Livellu assai più bassu.

Cumu hè cunnisciutu da a teoria di basa di dati relazionale, una bona implementazione di e transazzione deve risponde à i bisogni àcitu:

A - Atomicu (atomicità). Tutti i cambiamenti fatti in a transazzione o nimu in tuttu sò registrati.

C - Cuerenza. Dopu chì una transazzione cumpleta, u statu logicu di a basa di dati deve esse coherente internamente. In parechje manere, questu requisitu cuncerna u programatore, ma in u casu di basa di dati SQL cuncerna ancu e chjave straneri.

I - Isolate. E transazzioni in parallelu ùn devenu micca affettà l'altri.

D - Durable. Dopu a cumpiimentu successu di una transazzione, i prublemi à i livelli più bassi (fallimentu di energia, per esempiu) ùn deve micca affettà i dati cambiati da a transazzione.

Globali sò strutture di dati non-relazionale. Sò stati pensati per eseguisce super veloce nantu à hardware assai limitatu. Fighjemu l'implementazione di e transazzione in i globals usendu immagine ufficiale IRIS docker.

Per sustene e transazzione in IRIS, i seguenti cumandamenti sò usati: TSTART, TCOMMIT, TROLLBACK.

1. Atomicità

U modu più faciule per verificà hè l'atomicità. Avemu verificatu da a cunsola di basa di dati.

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

Allora cuncludemu:

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

Avemu ottene:

1 2 3

Tuttu hè bè. L'atomicità hè mantenuta: tutti i cambiamenti sò registrati.

Cumplichemu u compitu, intruduce un errore è vede cumu a transazzione hè salvata, parzialmente o micca in tuttu.

Cuntrollà dinò l'atomicità:

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

Allora fermaremu cù forza u cuntinuu, lanciamu è vedemu.

docker kill my-iris

Stu cumandamentu hè quasi equivalente à un arrestu di forza, postu chì manda un signalu SIGKILL per piantà u prucessu immediatamente.

Forse a transazzione hè stata salvata parzialmente?

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

- Innò, ùn hè micca sopravvissutu.

Pruvemu u cumandamentu di rollback:

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)

Nunda hè sopravvissutu ancu.

2. Cuerenza

Siccomu in basa di dati basati nantu à i globals, i chjavi sò ancu fatti nantu à i globals (lasciami ricurdà chì un globale hè una struttura di livellu più bassu per almacenà dati cà una tavola relazionale), per risponde à u requisitu di cunsistenza, un cambiamentu in a chjave deve esse inclusu. in a listessa transazzione cum'è un cambiamentu in u glubale.

Per esempiu, avemu una persona ^ mundiale, in quale guardemu personalità è usemu u TIN cum'è chjave.

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

Per avè una ricerca rapida per nome è nome, avemu fattu a chjave ^ index.

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

Per chì a basa di dati sia coherente, avemu da aghjunghje a persona cusì:

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

Dunque, quandu sguassate, duvemu ancu aduprà una transazzione:

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

In altri palori, u cumpletu di u requisitu di coerenza hè solu nantu à e spalle di u programatore. Ma quandu si tratta di globals, questu hè normale, per via di a so natura di livellu bassu.

3. Isolamentu

Hè quì chì cumincianu i salvatichi. Parechji utilizatori travaglianu simultaneamente nantu à a listessa basa di dati, cambiendu i stessi dati.

A situazione hè paragunabili à quandu parechji utilizatori travaglianu simultaneamente cù u stessu repository di codice è pruvate à cummette cambiamenti simultaneamente à parechji schedari à una volta.

A basa di dati deve risolve tuttu in tempu reale. In cunsiderà chì in l'imprese serii ci hè ancu una persona speciale chì hè rispunsevule per u cuntrollu di versione (per unisce rami, risolve i cunflitti, etc.), è a basa di dati deve fà tuttu questu in tempu reale, a cumplessità di u compitu è ​​a correttezza di u travagliu. disignu di basa di dati è codice chì serve.

A basa di dati ùn pò micca capisce u significatu di l'azzioni realizati da l'utilizatori per evità cunflitti si travaglianu nantu à e stesse dati. Puderà solu annullà una transazzione chì hè in cunflittu cù l'altru, o eseguisce sequentially.

Un altru prublema hè chì durante l'esekzione di una transazzione (prima di un impegnu), u statu di a basa di dati pò esse inconsistente, per quessa, hè desideratu chì l'altri transazzione ùn anu micca accessu à u statu inconsistente di a basa di dati, chì hè ottenuta in basa di dati relazionale. in parechje manere: creazione di snapshots, file multi-versione è etc.

Quandu eseguisce transazzione in parallelu, hè impurtante per noi chì ùn interferiscenu micca l'un l'altru. Questa hè a pruprietà di l'isolamentu.

SQL definisce 4 livelli di isolamentu:

  • LEGGIU SENZA IMPEGNI
  • LEGGIU IMMESSA
  • LEGGIU REPEATABLE
  • SERIALIZABLE

Fighjemu ogni livellu separatamente. I costi di implementazione di ogni livellu crescenu quasi in modu esponenziale.

LEGGIU SENZA IMPEGNI - questu hè u livellu più bassu di isolamentu, ma à u stessu tempu u più veloce. E transacciones ponu leghje i cambiamenti fatti da l'altri.

LEGGIU IMMESSA hè u prossimu livellu di isolamentu, chì hè un cumprumissu. E transazzioni ùn ponu micca leghje i cambiamenti di l'altri prima di l'impegnu, ma ponu leghje qualsiasi cambiamenti fatti dopu à l'impegnu.

Sè avemu una transazzione longa T1, durante u quali cummits hè accadutu in transazzioni T2, T3 ... Tn, chì hà travagliatu cù i stessi dati cum'è T1, allura quandu dumandate dati in T1 avemu da ottene un risultatu sfarente ogni volta. Stu fenominu hè chjamatu lettura non-repeatable.

LEGGIU REPEATABLE - in questu livellu di isolamentu ùn avemu micca u fenomenu di lettura non-repeatable, per u fattu chì per ogni dumanda di leghje dati, hè creatu un snapshot di i dati di u risultatu è quandu si reutilizanu in a listessa transazzione, i dati da a snapshot. hè utilizatu. Tuttavia, hè pussibule di leghje dati fantasma à questu livellu di isolamentu. Questu si riferisce à leghje novi fila chì sò stati aghjunti da transazzioni paralleli impegnati.

SERIALIZABLE - u più altu livellu di insulazione. Hè carattarizatu da u fattu chì e dati utilizati in ogni modu in una transazzione (lectura o cambià) diventanu dispunibuli per altre transazzione solu dopu à a fine di a prima transazzione.

Prima, fighjemu s'ellu ci hè isolamentu di l'operazioni in una transazzione da u filu principale. Andemu apre 2 finestri di terminal.

Kill ^t

Write ^t(1)
2

TSTART
Set ^t(1)=2

Ùn ci hè micca isolamentu. Un filu vede ciò chì face u sicondu chì hà apertu a transazzione.

Videmu se e transazzioni di diversi fili vede ciò chì succede in elli.

Apertemu 2 finestri di terminal è apre 2 transazzioni in parallelu.

kill ^t
TSTART
Write ^t(1)
3

TSTART
Set ^t(1)=3

E transazzione parallele vedenu i dati di l'altri. Dunque, avemu u più simplice, ma ancu u livellu di isolamentu più veloce, LEGGIU SENZA IMMISSIONE.

In principiu, questu puderia esse espertu per i globals, per quale u rendiment hè sempre statu una priorità.

E se avemu bisognu di un livellu più altu di isolamentu in l'operazioni nantu à i global?

Quì avete bisognu di pensà à perchè i livelli di isolamentu sò necessarii in tuttu è cumu funzionanu.

U più altu livellu di isolamentu, SERIALIZE, significa chì u risultatu di e transazzione eseguite in parallelu hè equivalente à a so esecuzione sequenziale, chì guarantisci l'absenza di collisioni.

Pudemu fà questu utilizendu chjusi intelligenti in ObjectScript, chì anu assai usi diffirenti: pudete fà chjusi regulari, incrementali, multiplici cù u cumandimu. LOCK.

I livelli di isolamentu più bassi sò cummercializazioni pensati per aumentà a velocità di a basa di dati.

Videmu cumu pudemu ottene diversi livelli di isolamentu usendu serrature.

Stu operatore permette di piglià micca solu chjusi esclusivi necessarii per cambià i dati, ma i cosiddetti chjusi spartuti, chì ponu piglià parechji filamenti in parallelu quandu anu bisognu di leghje dati chì ùn deve micca esse cambiatu da altri prucessi durante u prucessu di lettura.

Più infurmazione nantu à u metudu di bloccu in dui fasi in Russu è Inglese:

Bloccu in dui fasi
Bloccu in dui fasi

A difficultà hè chì durante una transazzione u statu di a basa di dati pò esse inconsistente, ma sta dati inconsistenti hè visibili à altri prucessi. Cumu evità questu?

Utilizendu chjusi, creeremu finestre di visibilità in quale u statu di a basa di dati serà coherente. È tuttu l'accessu à tali finestri di visibilità di u statu accunsentutu serà cuntrullatu da chjusi.

I chjusi spartuti nantu à i stessi dati sò riutilizzabili - parechji prucessi ponu piglià. Sti chjusi impediscenu altri prucessi da cambià dati, i.e. sò usati per furmà Windows di un statu di basa di dati coherente.

I chjusi esclusivi sò usati per i cambiamenti di dati - solu un prucessu pò piglià un tali serratura. Un serratura esclusiva pò esse pigliatu da:

  1. Ogni prucessu si i dati sò liberi
  2. Solu u prucessu chì hà una serratura spartuta nantu à sta dati è era u primu à dumandà una serratura esclusiva.

Transazzioni in InterSystems IRIS globals

A più stretta a finestra di visibilità, più l'altri prucessi anu da aspittà, ma u più coherente u statu di a basa di dati in questu pò esse.

READ_COMMITTED - l'essenza di stu livellu hè chì vedemu solu dati impegnati da altri fili. Se i dati in una altra transazzione ùn sò micca stati impegnati, allora vedemu a so versione antica.

Questu ci permette di parallelizà u travagliu invece di aspittà chì a serratura sia liberata.

Senza trucchi spiciali, ùn puderemu micca vede l'antica versione di e dati in IRIS, cusì avemu da fà fà cù i chjusi.

In cunsiquenza, avemu da aduprà chjusi spartuti per permette à i dati di leghje solu in i mumenti di cunsistenza.

Diciamu chì avemu una basa d'utilizatori ^persona chì trasferisce soldi l'una à l'altru.

Momentu di trasferimentu da a persona 123 à a persona 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)

U mumentu di dumandà a quantità di soldi da a persona 123 prima di debitu deve esse accumpagnatu da un bloccu esclusivu (per difettu):

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

È s'ellu ci vole à mustrà u statutu di u contu in u vostru contu persunale, allora pudete aduprà un serratura spartutu o micca aduprà per tuttu:

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

In ogni casu, se assumemu chì l'operazioni di basa di dati sò realizate quasi istantaneamente (lasciami ricurdà chì i globals sò una struttura di livellu assai più bassu cà una tavola relazionale), allora a necessità di stu livellu diminuisce.

LEGGIU REPEATABLE - Stu livellu di isolamentu permette parechje letture di dati chì ponu esse mudificate da transazzione simultanea.

In cunsiquenza, avemu da mette un serratura spartutu nantu à leghje i dati chì cambiamu è chjusi esclusivi nantu à e dati chì cambiamu.

Fortunatamente, l'operatore LOCK permette di listà in dettagliu tutti i chjusi necessarii, di quale pò esse assai, in una dichjarazione.

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

altre operazioni (à questu tempu i fili paralleli pruvate à cambià ^ persona (123, quantità), ma ùn pò micca)

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

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

Quandu listessi i chjusi separati da virgule, sò pigliati in sequenza, ma se fate questu:

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

tandu sò pigliatu atomically tutti à una volta.

SERIALIZZA - averemu da stabilisce chjusi in modu chì ultimamente tutte e transazzione chì anu dati cumuni sò eseguite sequentially. Per questu approcciu, a maiò parte di i chjusi duveranu esse esclusivi è pigliati nantu à i più chjuchi di u globale per u rendiment.

Se parlemu di debiting funds in a global ^persona, allura solu u nivellu di isolamentu SERIALIZE hè accettatu per questu, postu chì i soldi deve esse spentu strettamente sequentially, altrimenti hè pussibule di passà a stessa quantità parechje volte.

4. Durabilità

Aghju realizatu teste cù tagliu duru di u cuntinuu utilizendu

docker kill my-iris

A basa li tollerà bè. Nisun prublema hè statu identificatu.

cunchiusioni

Per i globals, InterSystems IRIS hà supportu di transazzione. Sò veramente atomichi è affidabili. Per assicurà a coherenza di una basa di dati basata nantu à i globals, i sforzi di u programatore è l'usu di e transazzione sò necessarii, postu chì ùn hà micca custruzzioni cumplessi cum'è e chjave straneri.

U livellu di isolamentu di i globals senza l'usu di chjusi hè LEGGIU UNCOMMITED, è quandu si usa chjusi pò esse assicuratu finu à u livellu SERIALIZE.

A correttezza è a rapidità di e transazzione nantu à i globals depende assai di l'abilità di u programatore: i chjusi più spartuti sò usati durante a lettura, u più altu hè u livellu di isolamentu, è i chjusi più stretti esclusivi sò presi, u più veloce u rendiment.

Source: www.habr.com

Add a comment