CATEGORII DOCUMENTE |
GESTIUNEA TRANZACTIILOR
Conceptul de gestiune a tranzactiilor se refera la problematica mentinerii intr-o stare consistenta a bazei de date in conditiile in care accesul la date se face intr-un regim concurent si este posibila aparitia unor defecte. In consecinta se disting doua domenii de sine statatoare in cadrul problematicii generale a gestiunii tranzactiilor :
Controlul concurentei
Se ocupa cu mecanismele de sincronizare a acceselor astfel incat sa fie mentinuta integritatea bazei de date. Atunci cand controlul concurentei este realizat prin mecanismele de blocare (care la ora actuala sunt cele mai raspandite) mai apare o problema, colaterala, si anume aceea a interblocarilor. Datorita importantei sale problema gestiuni interblocarilor este de multe ori tratata ca o problematica de sine statatoare a gestiunii tranzactiilor.
Rezistenta la defecte
Se refera la tehnicile prin care se asigura atat toleranta sistemului fata de aparitia unor defecte, cat si capacitatea de recuperare a acestuia, adica posibilitatea de revenire la o stare consistenta in urma aparitiei unui defect care a cauzat intrarea lui intr-o stare inconsistenta.
1 Definitia conceptului de tranzactie
Prin controlul concurentei si rezistenta la defecte se urmareste asigurarea consistentei si sigurantei bazei de date. O baza de date este intr-o stare consistenta daca respecta toate constrangerile de integritate a datelor definite asupra sa. In timpul operatiilor de adaugare, stergere si modificare, baza de date trece dintr-o stare in alta. Evident, starea rezultata dupa orice prelucrare asupra bazei de date trebuie sa fie o stare consistenta, chiar daca in timpul prelucrarii baza de date s-a aflat temporar intr-o stare inconsistenta.
Siguranta bazei de date se refera la toleranta acesteia fata de defecte si la capacitatea de recuperare dupa aparitia unui defect.
O tranzactie este o unitate logica de prelucrare care asigura consistenta si siguranta bazei de date. In principiu, orice executie a unui program se poate considera o tranzactie daca baza de date este intr-o stare consistenta atat inainte cat si dupa executia sa. Consistenta bazei de date este garanta independent de faptul ca :
In general, o tranzactie consta dintr-o secventa de operatii de citire si scriere a bazei de date, la care se adauga o serie de operatii de calcul. Baza de date poate fi intr-o stare temporar inconsistenta in timpul executarii tranzactiei dar trebuie sa fie in stari consistente atat inainte cat si dupa executia acesteia.
Tranzactiile ar trebui sa contina doar acele comenzi DML care realizeaza o singura modificare asupra datelor. De exemplu un transfer de fonduri (sa spunem 1000$) intre doua conturi ar trebui sa implice un debit al unui cont de 1000$ si un credit al altui cont de 1000$. Ambele actiuni ar trebui sa se incheie cu succes sau sa dea eroare impreuna. Creditul nu ar trebui executat fara debit.
Conditii de terminare a tranzactiilor
O tranzactie nu se termina intotdeauna cu succes totusi orice tranzactie trebuie sa se termine, indiferent de situatia existenta (chiar si in cazul unor defecte). Daca tranzactia reuseste sa execute cu succes toate operatiile prevazute, atunci aceasta se va termina printr-o operatie de validare (commit). In schimb, daca dintr-un motiv sau altul tranzactia nu reuseste sa-si execute complet operatiile prevazute, atunci se va termina printr-o operatie de abortare (abort sau rollback). Motivele pentru care o tranzactie se aborteaza sunt numeroase, ele pot fi interne tranzactiei sau externe acesteia (ex. : detectarea de catre SGBD a unei situatii de interblocare). In cazul abortarii, executia tranzactiei este oprita iar efectele tuturor operatiilor pe care le-a executat pana in acel moment sunt anulate astfel incat baza de date revine la starea de dinaintea lansarii tranzactiei.
Comanda de validare a unei tranzactii are dublu rol :
indica SGBD-ului momentul de la care efectele tranzactiei pot fi reflectate in baza de date si devin vizibile altor tranzactii ;
marcheaza momentul incepand de la care efectele tranzactiei nu mai pot fi anulate (tranzactia nu se mai poate aborta) si modificarile efectuate in baza de dte devin permanente.
Operatia de validare este vitala in cazul sistemelor concurente, deci acolo unde este posibila executarea in acelasi timp a mai multor tranzactii care acceseaza aceeasi baza de date. Prin validare se pot preveni o serie de fenomene nedorite cum este abortarea in cascada a tranzactiilor.
Sa presupunem ca o tranzactie T este abortata dupa ce a efectuat una sau mai multe operatii de actualizare a bazei de date. In acest caz datele alterate de catre tranzactia T vor fi readuse la valorile pe care le-au avut inainte de a fi modificate de aceasta. Este insa posibil ca unele dintre tranzactiile executate in mod concurent cu tranzactia T sa fi accesat aceste date inainte de abortarea lui T. Aceste tranzactii vor trebui sa fie, la randul lor, abortate deoarece au avut acces la date inconsistente din baza de date iar rezultatele produse de ele pot fi compromise. Acest efect se poate propaga in continuare si asupra altor tranzactii, pe un numar nedefinit de nivele, conducand la abortarea in cascada a tranzactiilor. Fenomenul este cunoscut in literatura de specialitate sub numele de efect domino.
Daca se foloseste un mecanism de validare care respecta cele doua reguli de mai sus, atunci aparitia fenomenului de abortare in cascada devine imposibila. Intr-adevar, conform primei reguli, nici o tranzactie nu va putea accesa datele modificate de tranzactia T decat dupa validarea acesteia. Pe de alta parte, conform regulii a doua, dupa validarea sa, tranzactia T nu mai poate fi abortata, deci nu poate declansa un lant de abortari in cascada.
Validarea unei tranzactii marcheaza, din punct de vedere logic, terminarea acesteia. Validarea nu se poate face inainte ca operatiile specificate prin codul tranzactiei sa fie executate integral si inainte ca tranzactia sa ajunga intr-o stare incepand de la care exista certitudinea ca nu mai poate fi abortata.
Pana in momentul validarii, actualizarile efectuate de tranzactie sunt invizibile alror tranzactii, au caracter tentativ si pot fi oricand revocate (odata cu abortarea tranzactiei). Dupa validare actualizarile se inscriu cu caracter permanent in baza de date si devin irevocabile. Dupa validare nu maie ste posibila abortatrea tranzactiilor.
Proprietatile tranzactiilor
Prin defintie, tranzactiile sunt unitati de executie care garanteaza consistenta si siguranta bazei de date. Pentru aceasta orice tranzactie trebuie sa satisfaca un set de patru conditii sintetizate in literatura de specialitate prin acronimul ACID - atomicitate, consistenta, izolare, durabilitate.
Atomicitatea
Se refera la faptul ca o tranzactie este considerata o unitate elementara de prelucrare. Aceasta inseamna ca executia unei tranzactii se face dupa regula totul sau nimic , adica ori sunt executate toate operatiile din tranzactie ori nu se executa nimic. Daca o tranzactie este intrerupta datorita unor cauze oarecare, atunci ii revine SGBD-ului sarcina de a asigura, intr-un fel sau altul, terminarea tranzactiei. Dupa eliminarea cauzei care a dus la intreruperea tranzactiei, in functie de stadiul de executie in care s-a aflat aceasta in momentul aparitiei intreruperii, SGBD-ul poate proceda intr-unul dintre modurile urmatoare :
fie completeaza operatiile ramase neexecutate din cadrul tranzactiei, terminand tranzactia cu succes
fie anuleaza toate efectele operatiilor executate pana in momentul intreruperii, terminand tranzactia prin abortare.
Consistenta
Consistenta unei tranzactii consta pur si simplu in corectitudinea ei. Orice tranzactie, daca este executata independent, trebuie sa mentina consistenta bazei de date. Altfel spus, o tranzactie este un program corect care transforma baza de date dintr-o stare consistenta intr-o alta stare consistenta a sa. Prin consistenta bazei de date intelegem satisfacerea tuturor constrangerilor de integritate, explicite sau implicite, cum ar fi :
unicitatea cheilor primare ;
integritatea referentiala ;
orice predicat exprimat in sens de constrangere de integritate asupra bazei de date.
Bineinteles ca este de neconceput verificarea tuturor acestor conditii dupa executarea fiecarei tranzactii. De aceea unicul criteriu pentru stabilirea proprietatii de consistenta a unei tranzactii ramane corectitudinea sa din punct de vedere logic. Spre deosebire de celelalte proprietati din complexul ACID, care sunt asigurate de catre sistem, proprietatea de consistenta a tranzactiei cade in sarcina programatorului de aplicatii. De remarcat faprul ca starile intermediare prin care trece baza de date in timpul executiei unei tranzactii nu sunt neaparat consistente.
Izolarea
Se refera la proprietatea oricarei tranzactii de a avea acces doar la starile consistente ale bazei de date. Aceasta inseamna ca modificarile efectuate de catre o tranzactie sunt inaccesible altor tranzactii concurente pana in momentul validarii acesteia. Prin proprietatea de izolare se creeaza iluzia ca fiecare tranzactie este executata singura in sistem. Utilizatorul care a lansat o tranzactie nu va percepe in nicu un fel (cel putin in ceea ce priveste rezultatele) faptul ca alte tranzactii sunt executate in acelasi timp. Izolarea tranzactiilor este asigurata prin algoritmi de control al concurentei.
Proprietatea de izolare este importanta deoarece elimina fenomenul de abortare in cascada a tranzactiilor (efect domino). Intr-adevar daca rezultatele incomplete ale unei tranzactii ar fi vizibile altor tranzactii inainte de validarea acesteia si daca se intampla ca aceasta tranzactie sa aborteze, atunci toate tranzactiile care au accesat rezultatele incomplete vor trebui abortate. Aceasta poate conduce la abortarea altor tranzactii s.a.m.d. rezultand efectul domino.
Durabilitatea
Durabilitatea unei tranzactii este proprietatea prin care se garanteaza faprul ca, odata tranzactia validata, rezultatele sale devin permanente si sunt inscrise in baza de date. Chiar daca dupa momentul validarii apare un defect care impiedica inscrierea normala a rezultatelor tranzactiei in baza de date, acestea vor fi trecute in baza de date dupa reluarea activitatii. Rezultatele tranzactiilor validate vor supravietui oricarei caderi de sistem.
Mecanismul prin care re realizeaza proprietatea de durabilitate are la baza conceptul de jurnal. Jurnalul este un fisier secvential in care sunt inregistrate toate operatiile efectuate de tranzactiile din sistem. Jurnalul contine istoria evolutiei integului sistem. El este folosit la reluarea activitatii de catre procedurile de recuperare care vor completa eventualele operatii neterminate ale tranzactiilor care au fost validate inainte de aparitia defectului.
Controlul tranzactiilor cu instructiuni SQL
Exista doua clase de tranzactii. Tranzactii DML - care contin un numar oarecare de blocuri DML si pe care ORACLE le trateaza ca o singura entitate sau o singura unitate logica de lucru, si tranzactii DDL care contin un singur bloc DDL.
O tranzactie noua este lansata fie imediat dupa conectarea la serverul de baze de date (de exemplu, printr-o sesiune SQL*Plus) fie dupa o comanda care a incheiat tranzactia precedenta (executia unui COMMIT sau ROLLBACK), cand este intalnit primul bloc executabil DML sau DDL. O tranzactie se termina in una din urmatoarele situatii :
* Intalnirea comenzior COMMIT/ROLLBACK
* Sfarsitul comenzii DDL
* Aparitia anumitor erori (DEADLOCK)
* Intalnirea comenzii EXIT - iesire din SQL*Plus
* Aparitia unei erori de sistem
Un bloc DDL este executat automat si de aceea implicit incheie o tranzactie. Dupa incheierea unei tranzactii, urmatorul bloc executabil SQL va lansa automat urmatoarea tranzactie.
Erorile de Sistem
Cand o tranzactie este intrerupta de o eroare serioasa, de exemplu o eroare de sistem, intreaga tranzactie este anulata. Aceasta previne erorile datorate modificarilor nedorite asupra datelor, si realizeaza intoarcerea tabelelor la starile de dupa ultimul COMMIT. In acest fel SQL protejeaza integritatea tabelelor. Anularea automata este cauzata cel mai des de catre o eroare de sistem, ca de exemplu o resetare a sistemului sau o cadere de tensiune. Erorile de tastare a comenzilor, ca de exemplu tastarea gresita a unor nume de coloane sau incercarile de a realiza operatii neautorizate asupra tabelelor altor utilizatori, nu intrerup tranzactia si nu realizeaza anularea automata. Aceasta se datoreaza faptului ca aceste erori sunt detectate in cursul compilarii (de catre PARSER, cand un bloc SQL este scanat si verificat), si nu in timpul executiei.
Urmatoarele instructiuni SQL sunt utilizate cand apar finalizari (commit) sau refaceri (rollback) :
* COMMIT[WORK]
* SAVEPOINT nume_savepoint
* ROLLBACK[WORK] to [SAVEPOINT] nume_savepoint;
De notat ca atat COMMIT cat si ROLLBACK sunt instructiuni SQL.
Cele trei instructiuni SQL utilizate pentru controlul tranzactiilor sunt explicate mai jos:
COMMIT[WORK]
Sintaxa : COMMIT[WORK];
* Permanentizeaza schimbarile din tranzactia curenta
* Sterge toate punctele de salvare (savepoint) din tranzactie
* Termina tranzactia
* Elibereaza toate blocarile (Lock) tranzactiei
* Cuvantul cheie WORK este optional
Utilizatorul trebuie sa expliciteze sfarsitul tranzactiei in programul aplicatie utilizand COMMIT (sau ROLLBACK). Daca nu se finalizeaza explicit tranzactia si programul se termina anormal, ultima tranzactie executata va fi anulata.
Finalizari implicite (commit) apar in urmatoarele situatii :
+ inainte de o comanda DDL
+ dupa o comanda DDL
+ la inchiderea normala a unei baze de date
Daca introduceti un bloc DDL dupa cateva blocuri DML, blocul DDL cauzeaza aparitia unui commit inaintea propriei executii, incheind tranzactia curenta. Apoi, daca blocul DDL este executat pana la capat, este si inregistrat (commit).
SAVEPOINT
Sintaxa : SAVEPOINT nume_savepoint
Exemplu :
SAVEPOINT terminare_actualizari
* Poate fi utilizat pentru a imparti o tranzactie in bucati mai mici
* Punctele de salvare (savepoints) permit utilizatorului sa retina toata munca sa la orice moment din timp, cu optiunea de a inregistra mai tarziu totul, a anula totul sau o parte din ea.
Astfel, pentru o tranzactie lunga, se pot salva parti din ea, pe masura executiei, la sfarsit inregistrandu-se sau refacandu-se continutul initial. La aparitia unei erori nu trebuie executat din nou fiecare bloc.
* La crearea unui nou punct de salvare cu acelasi nume ca al unuia dinainte, primul punct este sters.
* Numarul maxim de puncte de salvare pentru un proces utilizator este implicit 5. Aceasta limita poate fi schimbata.
ROLLBACK[WORK] to [SAVEPOINT] nume_punct_salvare
* Instructiunea ROLLBACK este utilizata pentru a reface starea bazei de date.
* Cuvantul cheie 'work' este optional. Intoarcerea la un punct de salvare este de asemenea optionala.
* Daca se utilizeaza ROLLBACK fara clauza TO SAVEPOINT, atunci :
+ se termina tranzactia
+ se anuleaza modificarile din tranzactia curenta
+ se sterg toate punctele de salvare din tranzactie
+ se elibereaza blocarile tranzactiei
Intoarcerea la Nivel de Bloc
O parte a unei tranzactii poate fi anulata. Daca un singur bloc DML da eroare, ORACLE va intoarce inapoi doar acel bloc. Aceasta facilitate este cunoscuta ca STATEMENT LEVEL ROLLBACK. Intoarcerea la nivel de bloc consta in faptul ca daca un singur segment DML da eroare la executia unei tranzactii, efectul lui este anulat, dar schimbarile realizate de precedentul bloc DML in tranzactie nu vor fi anulate si pot fi inscrise (COMMIT) sau intoarse (ROLLBACK) explicit de catre utilizator.
Daca blocul este unul de tip DDL, inscrierea (commit) care precede imediat acest bloc nu este anulata (schimbarile au fost facute deja permanente). ORACLE realizeaza intoarcerea la nivel de bloc prin crearea unui punct de salvare implicit inainte de executarea fiecarei comenzi DML. Utilizatorul nu poate referi acest punct de salvare in mod direct.
Astfel, daca va intoarceti la un punct de salvare, atunci:
* se anuleaza o parte din tranzactie ;
* se retine punctul de salvare pentru intoarcere, dar se pierd toate celelalte puncte create dupa punctul de salvare respectiv ;
* se elibereaza toate blocarile de tabele si linii.
Intoarceri implicite
Intoarcerile implicite apar cand se intalnesc terminari anormale ale executiei (de exemplu cand se intrerupe un proces utilizator). Intoarcerile implicite la nivel de bloc apar la eroarea de executie a unui bloc.
Este recomandat ca tranzactiile sa se termine explicit utilizand COMMIT[WORK] ori ROLLBACK[WORK].
Urmatorul exemplu ilustreaza utilizarea unui punct de salvare si a instructiunilor ROLLBACK si COMMIT.
INSERT INTO OFFICES VALUES
( 23, 'LAS VEGAS','WESTERN',null, null, 0 );
SAVEPOINT insert_done;
UPDATE SALESREPS
SET REP_OFFICE = 23, MANAGER=106;
ROLLBACK TO insert_done ( modificarile sunt abandonate );
UPDATE SALESREPS
SET REP_OFFICE = 23, MANAGER=106
WHERE EMPL_NUM=102 ; ( revizuim comanda UPDATE )
UPDATE OFFICES
SET MGR=102
WHERE OFFICE=23 ;
COMMIT;
AUTOCOMMIT
COMMIT sau ROLLBACK pot fi date manual sau automat, prin utilizarea optiunii AUTOCOMMIT a comenzii SET. Optiunea AUTOCOMMIT controleaza cand schimbarile dintr-o baza de date sunt facute permanente.
Exista doua setari :
COMANDA + DESCRIEREA
SET AUTO[COMMIT] ON
COMMIT este utilizat automat la fiecare INSERT, UPDATE sau DELETE
SET AUTO[COMMIT] OFF
COMMIT poate fi utilizata de utilizator explicit. De asemenea, COMMIT se executa dupa executia comenzilor DROP, ALTER, CREATE sau la iesirea din SQL*Plus. ROLLBACK poate fi executat explicit de catre utilizator pentru refacerea bazei de date.
De retinut ca SET este o comanda SQL*Plus.
2 Controlul concurentei
La sistemele in care o baza de date este accesata simultan de catre mai multi utilizatori apar situatii de coflict datorate accesului concurent la datele care constituie o resursa comuna.
Consistenta la citire
Utilizatorii bazelor de date fac doua tipuri de accesari asupra bazelor de date:
Operatii de citire ( SELECT )
Operatii de scriere ( INSERT, UPDATE, DELETE )
Cititorului si scriitorului unei baze de date trebuie sa i se garanteze o vedere consistenta asupra bazei de date. Cititorii nu trebuie sa vizualizeze o data care este in curs de modificare iar scriitorii trebuie sa fie siguri ca schimbarile dintr-o baza de date sunt facute intr-un mod consistent : schimbarile facute de un scriitor sa nu distruga sau sa intre in conflict cu schimbarile pe care le face un alt scriitor.
Scopul consistentei la citire este acela de a asigura faptul ca fiecare utilizator vede data ca fiind cea de la ultimul COMMIT, inainte ca o operatie DML sa inceapa. Consistenta la citire este implementata prin tinerea unor copii partiale ale bazei de date in segmente de intoarcere (ROLLBACK). Cand de executa operatii de scriere intr-o baza de date, ORACLE va face o copie a datelor inainte de schimbare si o va scrie intr-un segment de intoarcere. Toti cititorii, exceptandu-i pe cei care au facut schimbarile, inca mai vad baza de date care exista inainte ca schimbarile sa fie facute - ei vad segmentul de intoarcere de fapt.
Oricum, inainte ca schimbarile sa fie facute permanente in baza de date, doar utilizatorul care modifica datele poate sa vada baza de date cu alteratiile incorporate. Toti ceilalti vad baza de date nemodificata (fereastra din segmentul de intoarcere ). Aceasta garanteaza citirea unor date consistente care nu fac subiectul unor modificari in curs.
Cand executia unui bloc DML se incheie (commit), schimbarile facute in baza de date devin vizibile oricarui utilizator care executa SELECT. Modificarile sunt facute 'universale' si acum toti utilizatorii vad baza de date cu modificarile incorporate. Spatiul ocupat de catre 'vechile' date in segmentul de intoarcere este eliberat pentru a fi reutilizat.
Daca tranzactia este anulata (ROLLBACK), atunci toate schimbarile sunt 'anulate' :
Versiunea veche ('originala') a bazei de date aflata in segmentul de intoarcere este scrisa inapoi ('recuperata') in baza de date.
Toti utilizatorii vad baza de date existenta inainte de inceperea tranzactiei.
Tranzactii de citire
Implicit, modelul consistent al ORACLE DBMS garanteaza ca rezultatul executiei unui bloc este consistent. In anumite situatii se poate dori efectuarea unor interogari multiple, asupra datelor din mai multe tabele si se doreste asigurarea consistentei datelor. Adica, rezultatele din orice tabela sunt consistente in timp in raport cu rezultatele din orice alta tabela.
Comanda SQL : SET TRANSACTION READ ONLY este utilizata pentru a incepe o tranzactie de citire exclusiv.
Consistenta la citire pe care READ ONLY o furnizeaza este implementata in acelasi fel cu consistenta la nivel de bloc - utilizand segmente de intoarcere. Fiecare bloc vede implicit o fereastra consistenta a datelor la momentul inceperii blocului. Aceasta facilitate este foarte folositoare pentru rapoarte care efectueaza mai multe interogari asupra mai multor tabele, in timp ce alti utilizatori actualizeaza aceleasi tabele.
Observatii :
SET TRANSACTION READ ONLY este utilizata pentru a incepe o tranzactie doar de citire.
Sunt permise doar cereri ( blocuri SELECT ). Comenzile DML nu sunt permise. SELECT FOR UPDATE va genera o eroare.
O instructiune COMMIT, ROLLBACK, sau un bloc DDL va termina tranzactia de citire ( de retinut ca blocurile DDL genereaza implicit suprascrieri - COMMIT ). In cazul blocurilor DDL, nu este data nici o indicatie referitoare la faptul ca tranzactia se termina implicit.
In timpul tranzactiei de citire, toate cererile se refera la aceeasi copie a bazei de date ( schimbarile sunt efectuate inainte ca tranzactia de citire sa inceapa).
Alti utilizatori pot continua sa citeasca sau sa modifice datele.
Urmatoarele instructiuni pot fi rulate pentru a extrage datele din tabelele SALESREPS si OFFICES.
COMMIT;
SET TRANSACTION READ ONLY;
SELECT EMPL_NUM, NAME, REP_OFFICE, TITLE
FROM SALESREPS;
SELECT OFFICE, CITY, REGION
FROM OFFICES;
COMMIT;
Ultimul COMMIT este necesar pentru a termina explicit tranzactia de citire.
Niveluri de izolare a tranzactiilor
Serverul Oracle 9i garanteaza consistenta citirii datelor la nivel de fraza SQL insa nu garanteaza implicit consistenta la nivel de tranzactie, acest lucru depinzand de nivelul de izolare (seriala) a tranzactiilor.
Serializarea presupune derularea tranzactiilor fara nici o posibilitate de intercalare a operatiilor lor, fiind regula care impune programarea acestora in unitati atomice. Acest lucru inseamna ca, o data ce o tranzactie a devenit activa, prin executia primei operatii de citire sau scriere, tranzactiile initiate de alti utilizatori nu pot fi derulate (sunt blocate in stare de asteptare) pana cand cea dintai se incheie.
Totusi, nici un sistem de baze de date nu impune o planificare atat de stricta a operatiilor tranzactionale, din urmatorul motiv: intercalarea operatiilor tranzactionale ofera oportunitati deosebite de imbunatatire a performantelor in folosirea concurentiala a resurselor, lucru care se poate determina prin numarul de tranzactii incheiate intr-o anumita perioada de timp.
O astfel de abordare trebuie totusi sa respecte principiul seriabilizarii, in caz contrar fiind amenintata integritatea datelor. Cu alte cuvinte, chiar in conditii concurentiale, modul de derulare a tranzactiilor trebuie sa fie echivalent cu derularea seriala ca unitati atomice a acestora, adica situatia in care fiecare tranzactie s-ar fi derulat in ordine, dupa ce precedenta s-a incheiat complet.
Pentru a obtine un grad de concurenta mai ridicat s-a recurs la slabirea principiului seriabilizarii pentru a scadea numarul de tranzactii blocate in starea de asteptare. Consecinta mai putin dorita, dar acceptabila in anumite conditii, va fi scaderea gradului de izolare a tranzactiilor, crescand astfel posibilitatea executarii operatiilor tranzactionale intr-o ordine neechivalent serializabila.
Serverul de baze de date Oracle 9i suporta doua nivele de izolare a tranzactiilor, numite READ COMMITED si SERIALIZABLE, care pot fi obtinute daca la initierea unei noi tranzactii va fi execuata o comanda SET TRANSACTION de genul :
SET TRANSACTION ISOLATION LEVEL READ COMMITED ;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
Implicit (adica nefolosind comanda SET TRANSACTION in mod explicit), nivelul de izolare este READ COMMITED.
Figurile 1 si 2 prezinta un exemplu simplu in acest sens, prin doua sesiuni ce deruleaza tranzactii concurente astfel : in prima sesiune este adaugata o noua inregistrare care va deveni vizibila, imediat ce a fost comisa, si in a doua sesiune produnand un efect cunoscut drept citiri nerepetabile sau phanton reads.
SQL> SELECT * FROM SALESREPS ;
SQL> INSERT INTO SALESREPS
2 values (111, 'Sandra Grant', 30, 13, 'Sales Rep', '19-SEP-90', 104, null, 0) ;
1 row created.
SQL> COMMIT ;
Commit complete.
Figura 1 In prima sesiune adaugam o noua inregistrare si o comitem.
SQL> SET TRANSACTION ISOLATION LEVEL READ COMMITED ;
Transaction set.
SQL> SELECT * FROM SALESREPS ;
SQL> SELECT * FROM SALESREPS ;
Figura 2 In a doua sesiune, pe durata tranzactiei curente, starea tabelei SALESREPS se modifica
Daca vom modifica nivelul de izolare in SERIALIZABLE, atunci repetarea experimentului anterior va duce la un alt rezultat, si anume : inregistrarea comisa in prima sesiune va deveni vizibila si in cealalta abia dupa incheierea tranzactiei curente (dupa ROLLBACK sau COMMIT), vezi figurile 3 si 4.
SQL> INSERT INTO SALESREPS
values (1132, 'James Williams', 35, 11, 'Sales Rep', '08-APR-86', 106, null, 0) ;
SQL> COMMIT ;
Commit complete.
Figura 3 In prima sesiune adaugam o noua inregistrare si o comitem
SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
Transaction set.
SQL> SELECT * FROM SALESREPS ;
SQL> SELECT * FROM SALESREPS ;
SQL> ROLLBACK ;
Rollback complete.
SQL> SELECT * FROM SALESREPS ;
Figura 4 In a doua sesiune, actualizarile efectuate in tranzactiile concurente comise vor fi vizibile dupa incheierea tranzactiei curente (ROLLBACK)
Despre bocaje in tranzactii concurente
Derularea unui blocaj
Am exemplificat mai inainte derularea a doua tranzactii concurente ce vizau aceasi tabela, SALESREPS, dar in conditiile in care modificarile erau efectuate doar intr-una dintre ele. Ce s-ar intampla daca cele doua tranzactii vor incerca sa modifice in acelasi timp aceleasi inregistrari ?
Daca facem un experiment simplu si deschidem doua sesiuni in care se vor derula tranzactiii concurente, iar in prima sesiune sunt modificate (presupunem) datele vanzatorului cu id-ul 102, lucrurile vor decurge deocamdata fara nici o problema. Atunci cand in cea de-a doua sesiune vom incerca sa modificam tot datele vanzatorului cu id-ul 102, vom observa ca acesta va ramane suspendata pana cand tranzactia din prima sesiune se incheie. Explicatia fenomenului este urmatoarea : la nivelul tabelei SALESREPS, in momentul in care s-a produs o modificare asupra unei inregistrari, acesteia i-a fost asociat un marcaj de blocare care previne invocarea ei ulterioara din alte tranzactii concurente, marcaj care nu va fi anulat decat in momentul cand respectiva tranzactie este incheiata (explicit, prin COMMIT ori ROLLBACK, sau fortat, de catre serverul Oracle) .
Sistemul blocajelor este mecanismul care permite derularea tranzactiilor concurente intr-o maniera totusi cat mai aproape de principiul seriabilizarii, pentru a evita intercalarea operatiilor din tranzactiile concurente intr-un mod care sa afecteze integritatea si/sau consistenta datelor.
In aceasta privinta , serverul Oracle permite obtinerea blocajelor la doua nivele :
Moduri de blocare - parametri de initializare
Blocajele pot fi obtinute implicit, la initiativa serverului BD, atunci cand o tranzactie incepe executia unei fraze DML, sau la initiativa utilizatorilor (aplicatiilor) prin comenzi SQL explicite gen LOCK TABLE.
Comportamentul de blocare implicit al serverului BD este dependent de valoarea a doi parametri de initializare : ROW_LOCKING si SERIALIZABLE. Astfel, valoarea default pentru ROW_LOKING este always, ceea ce inseamna ca la executia unei fraze DML(update) se obtine automat blocarea liniilor vizate iar tabela este blocata in mod partajabil, permitand si altor tranzactii sa acceseze spre modificare alte linii. Daca modificam valoarea acestui parametru in intent, lucru realizabil in fisierul de initializare urmat de repornirea instantei, atunci simpla actualizare a unei linii va determina blocarea restrictiva a intregii tabele, astfel incat alte tranzactii concurente pot cel mult citi date, dar nu pot efectua modificari.
Cel de-al doilea parametru, SERIALIZABLE, se refera la nivelul de izolare si are implicit valoarea false sau disable, ecchivalenta cu READ COMMITED. Daca modificam valoarea acestui parametru in true, tranzactiile se vor derula echivalent SERIALIZABLE, fara a mai fi nevoie de executia comenzii SET TRANSACTION ISOLATION LEVEL SERIALIZABLE la inceputul lor.
Fisierul care contine parametrii de initializare se gaseste, de regula, in %ORACLE_HOME%admin<nume_serviciu_bd>pfile, iar dupa modificare instanta trebuie repornita.
Blocaje mortale (DEADLOCK)
Mecanismele de blocare a inregistrarilor au marele avantaj de a face posibila concurenta la nivelul tabelelor accesate simultan, totusi cu anumite amendamente. Acestea sunt legate de suspendarea pe timp indelungat a tranzatiilor care asteapta eliberarea anumitor blocaje sau, in cel mai rau caz, blocarea reciproca a doua tranzactii - deadlock.
Un blocaj mortal apare in cazul unui scenariu cum este cel prezentat in figura 5.
Tranzactia 1 Tranzactia 2
Timp x2 : Acceseaza/cere blocarea liniei N Blocheaza linia N |
Timp x4 : Acceseaza/cere blocarea liniei R Trece in asteptare DEADLOCK |
Timp x1 : Acceseaza/cere blocarea liniei R
|
Timp x3 : Acceseaza/cere blocarea liniei N Trece in asteptare |
Tabela
R | |
N | |
Figura 5 Scenariu de producere a unui deadlock
Un astfel de scenariu poate avea loc dupa cum este exemplificat in figurile 6 si 7 : se observa mai intai ca, la momentul T1, prima tranzactie acceseaza inregistrarea vanzatorului cu id-ul 102, iar la momentul T2, cea de-a doua tranzactie acceseaza inregistrarea vanzatorului cu id-ul 107. Apoi prima tranzactie incearca sa modifice inregistrarea cu id-ul 107, blocata anterior de cea de-a doua tranzactie, motiv pentru care va fi trecuta in asteptare . In sfarsit, cea de-a doua tranzactie incearca, la randul ei, sa modifice datele vanzatorului cu id-ul 102 si se impiedica de blocajul pe aceasta inregistrare initiat de prima tranzactie.
SQL> SELECT * FROM SALESREPS ;
SQL> SELECT TO_CHAR(SYSDATE,'HH24 :MI') t1 FROM dual ;
T1
SQL> UPDATE SALESREPS SET SALES=500000 WHERE EMPL_NUM=102 ;
1 row updated.
SQL> SQL> SELECT TO_CHAR(SYSDATE,'HH24 :MI') t3 FROM dual ;
T3
SQL> UPDATE SALESREPS SET SALES=255730 WHERE EMPL_NUM=107 ;
Figura 6 Derularea primei tranzactii pana la blocarea acesteia din cauza activitatii din cea de-a doua tranzactie.
SQL> SELECT * FROM SALESREPS ;
SQL> SELECT TO_CHAR(SYSDATE,'HH24 :MI') t2 FROM dual ;
T2
SQL> UPDATE SALESREPS SET QUOTA=250000 WHERE EMPL_NUM=107 ;
1 row updated.
SQL> SELECT TO_CHAR(SYSDATE,'HH24 :MI') t4 FROM dual ;
T4
SQL> UPDATE SALESREPS SET QUOTA=400000 WHERE EMPL_NUM=102 ;
Figura 7 Derularea celei de-a doua tranzactii pana la blocarea ei din cauza activitatii din prima tranzactie
Serverul Oracle are insa capacitatea de a detecta astfel de situatii de blocaj total si efectueaza un arbitraj obligand una dintre tranzactii sa renunte la modificarea curenta si genereaza un mesaj de eroare, similar cu cel din figura 8
SQL> UPDATE SALESREPS SET EMPL_NUM = 104 WHERE EMPL_NUM = 102 ;
UPDATE SALESREPS SET EMPL_NUM = 104 WHERE EMPL_NUM = 102
*
ERROR at line 1 :
ORA-00060 : deadlock detected while waiting for resource
Figura 8 Serverul BD a detectat un deadlock
Blocaje la nivel de tabela. Comenzile SQL LOCK TABLE
Pentru a defini mecanisme de blocare specifice, impuse de strategiile particulare de dezvoltare a aplicatiilor, se recomanda folosirea comenzilor SQL LOCK TABLE. Prin urmare, utilizatorii pot modifica sistemul de blocare sau modul de partajare a tabelelor, insa mecanismul de blocare exclusiva la nivel de linie nu poate fi ocolit sau dezactivat.
a) Protejarea liniilor modificate sau care urmeaza a fi modificate
Gradul de concurenta cel mai mare poate fi obtinut folosind la nivel de tabela blocaje gen ROW SHARE sau ROW EXCLUSIVE. Acestea se mai numesc si blocaje la nivel de date. Caracteristica lor definitorie rezida in faptul ca respectiva tabela este partajabila la nivelul liniilor, tranzactii concurente pot actualiza linii concurente din aceeasi tabela, dar se previne blocarea exclusiva pentru scriere a intregii tabele. Intre ele, aceste blocaje se diferentiaza prin faptul ca ROW SHARE blocheaza liniile din tabela in vederea unor actualizari viitoare iar ROW EXCLUSIVE blocheaza liniile ca efect al actualizarilor imediate (ca efect al executiei frazelor UPDATE, DELETE, INSERT).
Acest tip de blocaj se poate obtine in doua moduri :
Implicit, prin comenzi SELECT insotite de clauza FOR UPDATE, pentru ROW SHARE, si frazele obisnuite INSERT, UPDATE, DELETE pentru ROW EXCLUSIVE.
Explicit, prin urmatoarele comenzi :
LOCK TABLE nume_tabela IN ROW SHARE MODE ;
LOCK TABLE nume_tabela IN ROW EXCLUSIVE MODE ;
Un astfel de blocaj este necesar daca se intentioneaza cel putin modificarea ulterioara sau imediata a unor date disponibile, spre exemplu printr-o interfata grafica.
O fraza de genul
SELECT * FROM SALSESREPS
WHERE EMPL_NUM IN (102, 104) FOR UPDATE ;
Ar fi dus la evitarea deadlock-ului exemplificat in figurile 6, 7, 8 pentru ca ar fi prevenit modificarea inregistarilor respective prin tranzactii concurente.
b) Protejarea in totalitate a tabelelor fata de modificarile ce ar putea proveni din tranzactii concurente
Pe langa blocaje la nivel de date, in Oracle mai exista si blocajele SHARE, SHARE ROW EXCLUSIVE si EXCUSIVE, care previn modificarea din alte tranzactii a oricarei linii din tabela vizata. De obicei, aceste tipuri de blocaje sunt utilizate in situatii in care se doreste dobandirea exclusiva a dreptului de actualizare asupra unei tabele.
Blocajele SHARE sunt utilizate, in general, atunci cand in decursul unei tranzactii este necesara pastrarea nealterata a setului de inregistrari, astfel incat rezultatul interogarilor care implica tabela vizata sa fie consistent pana la sfarsitul tranzactiei.
Blocajele de tip SHARE ROW EXCLUSIVE sunt necesare atunci cand, in plus fata de ceea ce se poate realiza cu blocajele SHARE, se vizeaza si modificarea exclusiva a datelor din tabela. In mod normal, in conditiile unui singur blocaj SHARE din tranzactia care l-a intiat se poate realiza modificarea datelor din tabela implicata. Insa, spre deosebire de blocajele SHARE ROW EXCLUSIVE, care nu permit nici un alt fel de blocaj la nivel de tabela cu exceptia celor determinate de comenzi SELECT FOR UPDATE, blocajele SHARE simple pot fi paralelizate in tranzactii simultane, lucru ce va determina ca toate aceste tranzactii sa nu mai poata efectua modificari asupra tabelelor implicate.
Atat blocajele SHARE cat si cele SHARE ROW EXCLUSIVE sunt permisive in ceea ce priveste blocajele ROW SHARE la nivel de date. Prin urmare, tranzactiile care restrictive care au monopolizat momentan tabela la scriere permit altor tranzactii concurente sa blocheze anumite inregistrari, insa pentru modificari ulterioare si nu imediate. Aceasta situatie ascunde insa un potential de aparitie a fenomenelor dedlock, fiindca tranzactiile SHARE sau SHARE ROW EXCLUSIVE ar putea cere modificarea inregistrarilor blocate de catre alte tranzactii prin SELECT FOR UPDATE. In figurile 9 si 10 este prezentat un exemplu in acest sens.
SQL> SELECT TO_CHAR(SYSDATE,'HH24 :MI') t1 FROM dual ;
T1
SQL> LOCK TABLE SALESREPS IN SHARE ROW EXCLUSIVE MODE ;
Table(s) Locked.
SQL> SELECT TO_CHAR(SYSDATE,'HH24 :MI') t3 FROM dual ;
T3
SQL> UPDATE SALESREPS SET EMPL_NUM=112 WHERE EMPL_NUM=102 ;
Figura 9 Prima tranzactie care blocheaza tabela SALESREPS in mod SHARE ROW EXCLUSIVE
SQL> SELECT TO_CHAR(SYSDATE,'HH24 :MI') t2 FROM dual ;
T2
SQL> SELECT * FROM SALESREPS WHERE EMPL_NUM=102 FOR UPDATE ;
102 Sue Smith 48 21 Sales Rep 10-DEC-86 108 350.000,00 474.050,00
SQL> SELECT TO_CHAR(SYSDATE,'HH24 :MI') t4 FROM dual ;
T4
SQL> UPDATE SALESREPS SET EMPL_NUM=114 WHERE EMPL_NUM=104 ;
Figura 10 A doua tranzactie care blocheaza tabela SALESREPS in mod ROW SHARE prin SELECT FOR UPDATE
Scenariul prin care s-a obtinut fenomenul deadlock anterior este urmatorul : mai intai, prima tranzactie obtine un blocaj SHARE ROW EXCLUSIVE asupra tabelei SALESREPS, dupa care cea de-a doua tranzactie (concurenta cu prima) obtine si ea un blocaj ROR SHARE asupra aceleiasi tabele, pe inregistrarea vanzatorului cu id-ul 102, folosind o comanda SELECT FOR UPDATE. Apoi, prima tranzactie incearca actualizarea liniei cu id-ul 102 si ramAne suspendata ca urmare a blocarii anterioare a acestei linii in cealalta tranzactie. In fine, in a doua tranzactie se incearca modificarea unei linii oarecare din tabela SALESREPS si, ca urmare, apare un deadlock care va determina aparitia unei erori pe prima tranzactie (figura 11).
SQL> UPDATE SALESREPS SET EMPL_NUM=112 WHERE EMPL_NUM=102 ;
UPDATE SALESREPS SET EMPL_NUM=112 WHERE EMPL_NUM=102
*
ERROR at line 1 :
ORA-00060 :deadlock detected while waiting for resouce
Figura 11 Fenomenul deadlock relevat prin eroarea ORA-00060 aparuta in sesiunea primei tranzactii
Pentru a se evita astfel de situatii se recomanda folosirea blocajelor de tip EXCLUSIVE. Acestea dau exclusivitate la scriere si previn oricare alt blocaj (indiferent de tip) initiat dintr-o tranzactie concurenta. Fraza SQL prin care se poate invoca un astfel de blocaj este urmatoarea :
LOCK TABLE nume_tabela IN EXCLUSIVE MODE ;
Un tablou complet al modului in care sunt activate diversele tipuri de blocaje este prezentat in tabelul urmator :
Tabelul 1 Modul de obtinere a blocajelor
Fraza SQL |
Tip de blocaj la nivel de linie |
Tip de blocaj asupra tabelei |
SELECT . FROM nume_tabela | ||
INSERT INTO nume_tabela . |
X |
RX |
UPDATE nume_tabela . |
X |
RX |
DELETE FROM nume_tabela . |
X |
RX |
SELECT . FROM nume_tabela . FOR UPDATE OF . |
X |
RS |
LOCK TABLE nume_tabela IN . | ||
ROW SHARE MODE |
RS |
|
ROW EXCLUSIVE MODE |
RX |
|
SHARE MODE |
S |
|
SHARE EXCLUSIVE MODE |
SRX |
|
EXCLUSIVE MODE |
S |
|
X : exclusive RX : row exclusive |
RS : row share S : share SRX : share row exclusive |
Problema timpului in care o tranzactie ce solicita un blocaj la nivel de tabela ramane suspendata in stare de asteptare, ca urmare a conflictelor de blocare cu alte tranzactii concurente, este rezolvabila prin folosirea clauzelor NOWAIT in frazele SQL . FOR UPDATE si LOCK TABLE. In consecinta, daca un anumit tip de blocaj nu poate fi obtinut imediat, va fi generata o exceptie specifica. Iata un exemplu in acest sens :
SQL> SELECT TO_CHAR(SYSDATE,'HH24 :MI') t1 FROM dual ;
T1
SQL> LOCK TABLE SALESREPS IN EXCLUSIVE MODE NOWAIT ;
Table(s) Locked.
Figura 12 O prima tranzactie care solicita si obtine un blocaj EXCLUSIVE asupra tabelei SALESREPS
SQL> SELECT TO_CHAR(SYSDATE,'HH24 :MI') t2 FROM dual ;
T2
SQL> SELECT * FROM SALESREPS FOR UPDATE NOWAIT ;
SELECT * FROM SALESREPS FOR UPDATE NOWAIT
*
ERROR at line 1 :
ORA-00054 : resource busy and acquire with NOWAIT specified
Figura 13 A doua tranzactie solicita blocarea liniilor tabelei SALESREPS in modul ROW SHARE
Dupa cum se poate deduce din figura 12, prima tranzactie obtine un blocaj EXCLUSIVE , care va preveni aparitia altor blocaje concurente. In figura 13, a doua tranzactie solicita obtinerea unui blocaj prin comanda SELECT FOR UPDATE, a carei clauza NOWAIT va determina renuntarea la aceasta actiune daca blocajul nu poate fi obtinut imediat. Ca urmare, va fi generata eroarea ORA-00054.
Durata blocarilor
Toate blocarile acumulate de-a lungul unei tranzactii sunt eliberate cand tranzactia se termina.
Toate blocarile acumulate de-a lungul unei tranzactii sunt eliberate cand tranzactia se anuleaza .
Toate blocarile acumulate dupa un punct de salvare sunt eliberate cand tranzactia se intoarce la punctul de salvare.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 2247
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved