Scopul acestui capitol este acela de a arata cum ORACLE gestioneaza
blocarea.
Ariile acoperite sunt :
ORACLE utilizeaza blocarile pentru a controla accesul concurent la
date. Blocarile sunt mecanisme pentru a preveni interactiunea destructiva
intre utilizatorii care acceseaza aceleasi date.
Blocarile sunt utilizate pentru a atinge doua scopuri importante:
CONCURENTA DATELOR
CONSISTENTA LA CITIRE
Pentru a asigura concurenta datelor, ORACLE utilizeaza blocari si tranzactii. Blocarile sunt mecanisme utilizate pentru a preveni interactiunea destructiva intre utilizatorii care acceseaza aceleasi resurse.
Blocari de date ( DML locks )
Aceste blocari protejeaza datele. Blocarile de tabele blocheaza
intreaga tebela, in timp ce blocarile de coloane blocheaza doar coloanele
selectate.
Blocari de Dictionar ( Dictionary Locks )
Aceste blocari protejeaza structura de obiecte a bazei de date; de
exemplu ele protejeaza definitiile tebelelor si vederile (views). Blocarile
de dictionar sunt de doua tipuri : blocari sintactice (parser) si blocari
DDL.
In acest curs ne vom concentra doar asupra blocarilor de date.
Blocarile pot fi aplicate la nivelul unie tabele sau al unei linii.
Mod blocare Actiuni Actiuni Obtinut prin Prescurtare interzise permise comenzile SQL -------------------------------------------------------------------------- Share Modificari Blocare linii, LOCK TABLE tabela -S- RX,SRX,X RS,S,cereri IN SHARE MODE Exclusive Toate exceptand Cereri LOCK TABLE tabela -X- cereri,RS,RX,S, IN EXCLUSIVE MODE SRX,X si majoritatea blocurilor DDL Row share Acces exclusiv, Modificari, SELECT...FOR UPDATE, -RS- X RS,RX,S,SRX, LOCK TABLE tabela IN cereri ROW SHARE MODE Row exclusive Acces exclusiv modificari UPDATE,INSERT, -RX- pentru citire/ RX,RS, DELETE, LOCK TABLE scriere,S,SRX,X cereri tabela IN ROW EXCLUSIVE MODE Share row Citirea tabelei Blocare linii LOCK TABLE tabela exclusive in intregime,RX, RS,cereri IN SHARE ROW -SRX- S,SRX,X EXCLUSIVE MODE ---------------------------------------------------------------------------
Sumarul Blocarilor de Tabela (TM)
Blocurile care modifica linii explicite dintr-o tabela obtin mereu EXCLUSIVE ROW LOCKS (blocari exclusive de linie) si o blocare de tabela corespunzatoare.
Abreviatiile din paranteze sunt cele utilizate in Lock Monitor al
SQL*DBA.
Blocarile manuale pot fi cerute de optiunea NOWAIT atunci cand uti- lizatorul nu doreste sa astepte ca resursa blocata sa fie eliberata.
Blocarile care apar in timpul unui DML normal, fara o cerere specifica de blocare.
tabela +--------------+ ^ +----------------------+ | Utilizator A | | | | +--------------+ | +----------------------+ | | | # EXCLUSIVE | <-------------+ UPDATE, INSERT | +----------------------+ sau DELETE o linie | | | ROW | | EXCLUSIVE | | | | | | +----------------------+ | | # EXCLUSIVE | <-------------+ | +----------------------+ +------+-------+ | | | | Utilizator B | v +----------------------+ +--------------+ UPDATE, INSERT sau DELETE
Blocarea manuala poate fi preferata daca :
Blocurile de instructiuni care modifica blocarile implicite sunt :
Blocarile manuale pot fi preferate blocarilor implicite in multe cazuri. Acestea pot include vizualizarea consistenta a unor tabele. Un exemplu poate fi un master si cateva tabele detaliate.
O tranzactie poate dori schimbarea unor date bazata pe alte inregistrari, dar inregistrarea respectiva nu trebiue modificata pana cand nu se termina toata tranzactia.
Un bloc nu trebuie sa astepte dupa nici un alt bloc ca sa se termine evitandu-se astfel conflictele de blocare.
Comanda LOCK TABLE
Comanda LOCK TABLE este utilizata pentru a bloca la nivel de tabela explicit :
LOCK TABLE tabela, tabela, ... IN mod_de_blocare [NOWAIT]
Instructiunea SELECT FOR UPDATE
SELECT FOR UPDATE va suprascrie mecanismul implicit de blocare. Este utilizata inaintea executiei unei modificari ( update ). Diferenta dintre SELECT FOR UPDATE si UPDATE este aceea ca SELECT FOR UPDATE blocheaza lini ile mai devreme in tranzactie. Mai intai se executa cererea de identificare a liniilor ce vor fi modificate si dupa aceea blocheaza setul de linii, per mitand ca schimbarile sa aiba loc mai tarziu.
Sintaxa : SELECT ... FOT UPDATE [ OF coloana, coloana, ... ] [NOWAIT]
SELECT FOR UPDATE este recomandata pentru cazul cand se doreste blocarea unei linii fara modificare de exemplu, daca se doreste pornirea unei modificari a unor valori deja existente in linii, liniile nu trebuie sa poata fi modificare de catre altcineva inainte de suprascriere.
O cerere SELECT FOR UPDATE elibereaza blocarile la COMMIT sau ROLLBACK. Este indicat sa se utilizeze SELECT FOR UPDATE pentru cateva linii decat pentru un numar mare de linii.
+---------------------------+ | | 1. ROW LOCK(X) | | | | 2. TABLE LOCK(RS) | 1. SELECT...FOR UPDATE OF | | | | | 3. TABLE LOCK(RX) | | +---------------------------+
Este foarte posibil intr-un mediu multi-utilizator, ca utilizatorii isi vor bloca unii altora resursele. Este de asemenea posibil ca doi utilizatori sa sfarseasca prin a-si bloca unul altuia resurse diferite. Aceasta situatie se numeste DEADLOCK deoarece fiecare utilizator asteapta sesursele detinute de celalalt utilizator.
De exemplu : Tranzactia A Tranzactia B UPDATE EMP UPDATE EMP SET SAL=1200 SET SAL=1000 WHERE ENAME = 'SMITH'; WHERE ENAME = 'JONES'; UPDATE EMP UPDATE EMP SET SAL=2200 SET SAL=1350 WHERE ENAME = 'JONES'; WHERE ENAME = 'SMITH';
Cand primul bloc este executat, nu exista nici o problema. Oricum, cand ei vor incerca sa obtina blocarile pentru al doilea bloc, se va astepta in spatele celuilalt utilizator. Este deadlock deoarece nici macar prin asteptare problema nu va fi rezolvata.
Cand ORACLE detecteaza un deadlock, genereaza o eroare la unul dintre participantii tranzactiei, si intoarce blocul curent al tranzactiei respective. Aceasta rezolva deadlock-ul, astfel celalalt utilizator poate inca astepta pana cand resursa este disponibila. Utilizatorul semnalizat ar trebui sa execute explicit un ROLLBACK in tranzactie.
Deadlock-ul poate fi evitat daca utilizatorii care acceseaza
aceleasi tabele blocheaza tabelele in aceeasi ordine ca ceilalti. Ar trebui
predefinita o ordine de acces pentru toate tabelele in aplicatii si
aplicatiile astfel construite incat sa urmeze ordinea specificata. Daca
aceasta ordine este urmata in toate aplicatiile, probabilitatea de aparitie
a dead-lock va fi minima.
Blocarile de date sunt eliberate de :
Orice bloc explicit DDL. ROWID (id. de linie) si Blocarea COL ROWID VALOARE_NOUA IDENTIFICATOR_LINIE NOPRINT SELECT ENAME, JOB, HIREDATE SAL, ROWID FROM EMP WHERE WNAME = 'SCOTT' FOR UPDATE +--------------------+ ROWID | 00004C90.0001.0001 | +--------------------+ UPDATE EMP SET JOB = 'SALESMAN, HIREDATE=SYSDATE, SAL=1.1*SAL WHERE ROWID='&ROW_IDENT'
Este important sa se eexcute COMMIT cat mai cutand posibil pentru ca
blocarile sa fue eliberate devreme.
Procesul COMMIT poate fi accelerat prin folosirea ROWID pentru a localiza liniile in tabele. ROWID este o pseudo-coloana care are cate o valoare pentru fiecare linie din tabela. ROWID ne spune adresa unei linii si prin aceasta este cea mai rapida cale de acces disponibila. Intoarce trei parti de informatie necesare pentru a localiza o linie :
ROWID 00004C90.0001.0001
Cand este creat ROWID ?
ROWID este creat automat de ORACLE cand o linie este modificata cu succes intr-o tabela de baze de date; cand o inserare este facuta permanenta.
De ce sa utilizam ROWID ?
ROWID are cateva utilizari importante :
De notat ca se poate executa UPDATE / DELETE pe o linie cu ROWID doar daca linia respectiva a fost inainte blocata (adica SELECT FOR UPDATE).