Upload
vudang
View
213
Download
0
Embed Size (px)
Citation preview
Anca Ion, PBD, 2010
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.
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.
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;
Anca Ion, PBD, 2010
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
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('Inserts have been rolled back');
END;
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 salvare pana la care s-au anulat efectele nu este sters. Un simplu
rollback sau commit sterge 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.
Anca Ion, PBD, 2010
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;
Setarea proprietatilor tranzactiilor cu comanda SET TRANSACTION
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 aceleasi 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.
Anca Ion, PBD, 2010
Restrictiile operatiei SET TRANSACTION
Numai comenzile SELECT INTO, OPEN, FETCH, CLOSE, LOCK TABLE, COMMIT si
ROLLBACK sunt permise intr-o tranzactie read-only.
2. SET TRANSACTION READ WRITE
Aceasta tranzactia 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)
3. ISOLATION LEVEL CLAUSE
Folosirea clauzei ISOLATION LEVEL specifica cum sunt administrate tranzactiile care contin modificari ale bazei de date.
Setarea la SERIALIZABLE: daca o tranzactie 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 curente serializabile, atunci DML esueaza.
Setarea la READ COMMITTED: daca o tranzactie 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.
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
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
Anca Ion, PBD, 2010
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 operatii pana cand va putea bloca randurile. Daca se omite NOWAIT, Oracle va astepta pana cand
inregistrarile sunt disponibile.
Cand se interogheaza tabele multiple, randurile din tabele sunt blocate numai daca clauza 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;
Consideram 2 sesiuni SQL:
Sesiunea I
Anca Ion, PBD, 2010
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 a fi executata daca inainte executam COMMIT sau ROLLBACK pentru a elibera
blocarea asupra inregistrarii.
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;