Sunteți pe pagina 1din 5

SGBD ORACLE - LABORATOR 11

Laborator Procesarea Tranzactiilor in PL/SQL


Procesarea tranzactiilor se face folosind instructiunile COMMIT, SAVEPOINT si ROLLBACK care asigura consistenta bazei de date.
Procesarea tranzactiilor este o caracteristica a ORACLE, disponibila in toate limbajele de programare, care permite utilizatorilor sa
lucreze concurent pe baza de date, si asigura ca fiecare utilizator vede o versiune consistenta de date si toate schimbarile sunt aplicate
in ordinea corecta.

1. Folosirea comenzii COMMIT in PL/SQL


Comanda COMMIT termina tranzactia curenta, facand modificari permanente in baza de date si vizibile utilizatorilor. Tranzactiile nu
sunt cuprinse in blocuri BEGIN-END in PL/SQL. Un bloc poate contine mai multe tranzactii sau o tranzactie poate imparti mai multe
blocuri.

Exemplu: o tranzactie care transferabani dintr-un cont bancar in altul. Este important ca banii sa fie scosi dintr-un cont si pusi in altul
in acelasi moment. Altfel pot aprea probleme ca pierderea banilor sau duplicarea lor in ambele conturi.

CREATE TABLE accounts (account_id NUMBER(6), balance NUMBER (10,2));


INSERT INTO accounts VALUES (7715, 6350.00);
INSERT INTO accounts VALUES (7720, 5100.50);
DECLARE
transfer NUMBER(8,2) := 250;
BEGIN
UPDATE accounts SET balance = balance - transfer WHERE account_id = 7715;
UPDATE accounts SET balance = balance + transfer WHERE account_id = 7720;
COMMIT COMMENT 'Transfer From 7715 to 7720'
END;

Clauza optionala COMMENT permite specificarea unui comentariu asociat tranzactiei. Daca reteaua sau calculatorul cad in timpul
opratiei commit, starea tranzactiei poate fi necunoscuta. In acest caz Oracle memoreaza textul specificat de COMMENT in dictionarul
de date impreuna cu ID tranzactiei.

2. Folosirea comenzii ROLLBACK in PL/SQL


Comanda ROLLBACK termina tranzactia curenta si anuleaza toate schimbarile facute in timpul tranzactiei. Daca s-a sters din greseala
o inregistrare din tabela, aceasta oparatie anuleaza efectul stergerii. Daca nu se doreste terminarea unei tranzactii in momentul in care
apare o eroare, operatia rollback permite actiunea de anulare.

Exemplu: inserarea informatiei despre un angajat in 3 tabele diferite. Daca se incearca inserarea unui angajat cu id duplicat, exceptia
predefinita DUP_VAL_ON_INDEX este generata. Pentru a ne asigura ca schmibarile la cele 3 tabele sunt anulate, managerul erorii va
executa operatie ROLLBACK.

CREATE TABLE emp_name AS SELECT employee_id, last_name FROM employees;


CREATE UNIQUE INDEX empname_ix ON emp_name (employee_id);
CREATE TABLE emp_sal AS SELECT employee_id, salary FROM employees;
CREATE UNIQUE INDEX empsal_ix ON emp_sal (employee_id);
CREATE TABLE emp_job AS SELECT employee_id, job_id FROM employees;
CREATE UNIQUE INDEX empjobid_ix ON emp_job (employee_id);

DECLARE
emp_id NUMBER(6);
emp_lastname VARCHAR2(25);
emp_salary NUMBER(8,2);
emp_jobid VARCHAR2(10);
BEGIN
SELECT employee_id, last_name, salary, job_id INTO emp_id, emp_lastname,emp_salary, emp_jobid
FROM employees WHERE employee_id = 120;
INSERT INTO emp_name VALUES (emp_id, emp_lastname);
INSERT INTO emp_sal VALUES (emp_id, emp_salary);
INSERT INTO emp_job VALUES (emp_id, emp_jobid);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN

1
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('Inserts have been rolled back');
END;

3. Fosirea comenzii SAVEPOINT in PL/SQL


SAVEPOINT denumeste si marcheaza punctul curent din procesarea tranzactiei. Punctele de salvare permit sa nu se anuleaza
efectele intregii tranzactii ci numai o parte din ele sa fie anulate. Numarul de puncte de salavare dintr-o sesiune este nelimitat.

Exemplu: marcarea unui punct de salvare inainte de o operatie de insetare. Daca se insereaza o inregistrare duplicat apere eroarea
predefinita DUP_VAL_ON_INDEX. In acest caz se vor anula efectele pana la punctul de salvare, adica efectele operatiei de inserare
numai.

CREATE TABLE emp_name AS SELECT employee_id, last_name, salary FROM employees;


CREATE UNIQUE INDEX empname_ix ON emp_name (employee_id);

DECLARE
emp_id employees.employee_id%TYPE;
emp_lastname employees.last_name%TYPE;
emp_salary employees.salary%TYPE;
BEGIN
SELECT employee_id, last_name, salary INTO emp_id, emp_lastname,
emp_salary FROM employees WHERE employee_id = 120;
UPDATE emp_name SET salary = salary * 1.1 WHERE employee_id = emp_id;
DELETE FROM emp_name WHERE employee_id = 130;
SAVEPOINT do_insert;
INSERT INTO emp_name VALUES (emp_id, emp_lastname, emp_salary);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK TO do_insert;
DBMS_OUTPUT.PUT_LINE('Insert has been rolled back');
END;

Cand se anuleaza efectele pana la un punct de salvare, toate punctele de salvare dupa acesta sunt sterse. Punctul de slvare pana la
care s-au anulat efectele nu este sters. Un simplu rollback sau commit sterg toate punctele de salvare.

Punctele de salvare sunt identificatori nedeclarati. Refolosirea lor intr-o tranzactie muta punctul de salvare de la vechea pozitie la
pozitia curenta din tranzactie. Aceasta inseamna ca operatia rollback la punctul de salvare afecteaza numai partea pana curenta din
tranzactie.

Exemplu : refolosirea SAVEPOINT cu ROLLBACK

CREATE TABLE emp_name AS SELECT employee_id, last_name, salary FROM employees;


CREATE UNIQUE INDEX empname_ix ON emp_name (employee_id);

DECLARE
emp_id employees.employee_id%TYPE;
emp_lastname employees.last_name%TYPE;
emp_salary employees.salary%TYPE;
BEGIN
SELECT employee_id, last_name, salary INTO emp_id, emp_lastname,
emp_salary FROM employees WHERE employee_id = 120;
SAVEPOINT my_savepoint;
UPDATE emp_name SET salary = salary * 1.1 WHERE employee_id = emp_id;
DELETE FROM emp_name WHERE employee_id = 130;
SAVEPOINT my_savepoint; -- move my_savepoint to current poin
INSERT INTO emp_name VALUES (emp_id, emp_lastname, emp_salary);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK TO my_savepoint;
DBMS_OUTPUT.PUT_LINE('Transaction rolled back.');
END;

2
4. Setarea proprietatilor tranzactiilor cu comanda SET TRANSACTION
4.1. SET TRANSACTION READ ONLY

SET TRANSACTION se foloseste pentru a incepe o tranzactie read-only sau read-write, pentru a stabili un nivel de izolare sau pentru
a atribui tranzactia curenta unui anumit segment de rollback. Tranzactiile “read-only “ sunt folosite pentru a executa mai multe
interogari “select” in timp ce alti utilizatori modifica acelasi tabele.

Exemplu : managerul unui magazin foloseste o tranzactie read-only pentru a afisa totatulul tranzactiilor pe zi si pe luna trecuta.
Totalurile sunt neafectate de alte modificari pe baza de date in timpul tranzactiei.

DECLARE
daily_order_total NUMBER(12,2);
weekly_order_total NUMBER(12,2);
monthly_order_total NUMBER(12,2);
BEGIN
COMMIT; -- ends previous transaction
SET TRANSACTION READ ONLY NAME 'Calculate Order Totals';
SELECT SUM (order_total) INTO daily_order_total FROM orders
WHERE order_date = SYSDATE;
SELECT SUM (order_total) INTO weekly_order_total FROM orders
WHERE order_date = SYSDATE - 7;
SELECT SUM (order_total) INTO monthly_order_total FROM orders
WHERE order_date = SYSDATE - 30;
COMMIT; -- ends read-only transaction
END;

Daca o tranzactie este setata READ ONLY, toate interogarile din tranzactie vor vedea numai schimbarile efectuate inainte de a incepe
tranzactia. Folosirea unei tranzactii READ ONLY nu afecteaza alti utilizatori sau alte tranzactii.

Restrictiile operatiei SET TRANSACTION

Numai comenzile SELECT INTO, OPEN, FETCH, CLOSE, LOCK TABLE, COMMIT si ROLLBACK sunt permise intr-o tranzactie read-
only.

4.2. SET TRANSACTION READ WRITE

Acesta este implicit in Oracle. O posibila operatie din tranzactie poate vizualiza numai datele care au fost deja
terminate (comise) inainte ca opratia respectiva sa inceapa (si nu cand tranzactia a inceput)

4.3. ISOLATION LEVEL CLAUSE

Folosirea clauzei ISOLATION LEVEL specifica cum sunt administrate tranzactiile care contin modificari ale bazei de date.

 Setarea la SERIALIZABLE : specifica ca o tranzactie care contine limbaj de manipulare a datelor(DML) care asteapta
modificarea oricarei resurse care a fost modificata intr-o alta tranzactie neterminata inca la inceputul tranzactiei serializabile,
atunci DML esueaza.
 Setarea la READ COMMITTED: specifica ca o tranzactie care contine limbaj de manipulare a datelor(DML) care cere
blocarea unor inregistrari detinute de alta tranzactie, atunci operatiile DML asteapta pana ce blocarile sunt eliberate.

5. Blocari
Implicit, Oracle blocheaza structurile de date - o caracteristica importanta pentru Oracle.

Exista 2 tipuri de blocari:

a. Blocare la nivelul inregistrarii


b. Blocare la nivelul tabelei

Se pot cere blocari de date pe anumite inregistrari sau pe tabele intregi daca este nevoie sa se rescrie blocarile implicite. Blocarile
explicite permit blocarea accesului la date in timpul unei tranzactii.

 Cu comanda LOCK TABLE se poate bloca o tabela intreaga


 Cu comanda SELECT FOR UPDATE se pot bloca explicit anumite randuri(rows) pentru a se asigura ca ele nu schimba

3
Folosirea clauzei FOR UPDATE

Cand se declara un cursor care va fi referit in operatii UPDATE sau DELETE trebuie folosita clauza FOR UPDATE pentru a obtine
blocare exclusiva pe inregistrari

DECLARE
CURSOR c1 IS SELECT employee_id, salary FROM employees
WHERE job_id = 'SA_REP' AND commission_pct > .10
FOR UPDATE NOWAIT;

Comanda SELECT ... FOR UPDATE identifica inregistrarile care vor fi modificate sau sterse, apoi blocheaza fiecare rand din setul
rezultat. Aceasta este folositoare cand se doreste o modificare pe valorile existente din inregistrare(row). In acest caz trebuie asigurat
ca nu se efectueaza modificari asupra randului de catre alt utilizator inainte de update.

Cuvantul cheie optional NOWAIT precizeaza ca nu trebuie asteptat daca randurile cerute au fost blocate de alt utilizator. Controlul este
imediat intors in program pentru a efectua alte oparatii pana cand va putea bloca randurile. Daca se omite NOWAIT, Oracle va astepta
pana cand inregistrarile sunt desponibile.

Cand se interogheaza tabele multiple, randurile din tabele sun blocate numai daca caluza FOR UPDATE OF refera o coloana din acea
tabela. De exemplu, urmatoarea interogare blocheaza randurile din tabela employees, dar nu si din tabela departments.

DECLARE
CURSOR c1 IS SELECT last_name, department_name FROM employees, departments
WHERE employees.department_id = departments.department_id
AND job_id = 'SA_MAN'
FOR UPDATE OF salary;

Exemplu: folosirea clauzei CURRENT OF intr-o instructiune UPDATE sau DELETE pentru a referi ultima inregistrare returnata de un
cursor.

DECLARE
my_emp_id NUMBER(6);
my_job_id VARCHAR2(10);
my_sal NUMBER(8,2);
CURSOR c1 IS SELECT employee_id, job_id, salary FROM employees FOR UPDATE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO my_emp_id, my_job_id, my_sal;
IF my_job_id = 'SA_REP' THEN
UPDATE employees SET salary = salary * 1.02 WHERE CURRENT OF c1;
END IF;
EXIT WHEN c1%NOTFOUND;
END LOOP;
END;

Exemplu de autoblocare: Consideram 2 sesiuni SQL:

Sesiunea I

SQL> SELECT Salary


FROM employees
WHERE employee_id = 100
FOR UPDATE OF salary;

Sesiunea II

SQL> update employees


set salary=20000
where employee_id=100;

Tranzactia va esua, deoarece in Sessiunea 1 inregistrarea a fost blocata. Tranzactia din sesiunea 2 va fi executata daca inainte
executam COMMIT sau ROLLBACK pentru a elibera blocarea asupra inregistrarii.

4
Sesiunea I

SQL> SELECT Salary


FROM employees
WHERE employee_id = 100
FOR UPDATE OF salary;

SQL> rollback;

Rollback complete.

SQL>

Sesiunea II

SQL> update employees


set salary=20000
where employee_id=100;

S-ar putea să vă placă și