6
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;

Procesarea Tranzactiilor in PL/SQL - software.ucv.rosoftware.ucv.ro/~cstoica/DD/Laborator10.pdf · Daca s-a sters din greseala o inregistrare din tabela, aceasta oparatie anuleaza

  • 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;