Transakční zpracování v SQL P. Částek
Transakce Transakce = logická jednotka práce Podaří-li se všechny části transakce, potvrdíme je. COMMIT Jestliže se některá část transakce nepodaří, nastane nekonzistentní stav. Potřebujeme tedy všechny změny provedené zbylou částí transakce vrátit zpět (zrušit). ROLLBACK
Příklad Potřebujeme upravit více záznamů najednou. Buď všechny, nebo nastane-li při některé úpravě chyba, pak žádné. int zakazka_ = 1000; zakazky_celkem_ = zakazky_celkem_ ; EXEC SQL WHENEVER SQLERROR DO undo() ; EXEC SQL INSERT INTO zakazky ( cena ) VALUES ( :zakazka_ ) ; EXEC SQL UPDATE aktiva SET zakazky_celkem=:zakazky_celkem_ ; EXEC SQL COMMIT ; void undo() { EXEC SQL ROLLBACK ; }
V případě chyby… Před zpracováním zakazky: … aktiva: 5000 INSERT chyba UPDATE zakazky: … 1000 aktiva: 5000 INSERT UPDATE chyba zakazky: … 1000 aktiva: Po příkazu ROLLBACK zakazky: … aktiva: 5000 Tento případ nastat nemůže – SQL příkazy jsou sami o sobě atomické.
Transaction manager (TM) Příkazy jazyků DDL, DML a DCL jsou příkazy databáze. Příkazy COMMIT a ROLLBACK jsou příkazy transakčního manažeru. TM není součástí databáze – databáze je podřízená transakčnímu manažeru. Jak pracuje: UPDATE WHERE 1.DB vyhledá řádky odpovídající podmínce za WHERE 2.TM zapíše jejich stav do logu 3.DB změní tyto řádky 4.Dojde-li k vyvolání příkazu ROLLBACK, TM obnoví stav změněných řádků z logu
Bod synchronizace = „synchpoint“ Hraniční bod mezi dvěma po sobě následujícími transakcemi tj. na konci každé transakce, kdy je DB v konzistentním stavu Je založen na začátku aplikace, a dále při příkazech COMMIT a ROLLBACK.
COMMIT a ROLLBACK COMMIT Označuje úspěšný konec transakce Zakládá bod synchronizace Potvrdí všechny změny od předchozího bodu synchronizace, tyto změny se stávají nevratné. Zavře všechny otevřené kurzory; otevře zámky na všech záznamech ROLLBACK Označuje neúspěšný konec transakce Zakládá bod synchronizace Vrátí zpět všechny změny od předchozího bodu synchronizace Zavře všechny otevřené kurzory; otevře zámky na všech záznamech
COMMIT a ROLLBACK Každý SQL příkaz je vykonáván v rámci nějaké transakce – včetně DDL (CREATE) a DCL (GRANT). Dojde-li k vyvolání příkazu ROLLBACK, jsou zrušeny i takové změny. Transakce nemohou být vnořené jedna v druhé, nebo se prolínat – každý COMMIT a ROLLBACK ukončuje jednu transakci a začíná druhou
Tři konkurenční problémy The lost update problem The uncommitted dependency problem The inconsistent analysis problem
The lost update problem Proces 1 FETCH R UPDATE R Proces 2 FETCH R UPDATE R ČASČAS
The uncommitted dependency problem 1 Proces 1 FETCH R Proces 2 UPDATE R ROLLBACK ČASČAS
The uncommitted dependency problem 2 Proces 1 UPDATE R Proces 2 UPDATE R ROLLBACK ČASČAS
The inconsistent analysis problem Proces 1 FETCH R1 (30) suma = 30 FETCH R2 (30) suma = 60 Proces 2 FETCH R2 (40) UPDATE R2 (40 -> 30) FETCH R1 (30) UPDATE R1 (30 -> 20) COMMIT ČASČAS
Tři konkurenční problémy The lost update problem The uncommitted dependency problem The inconsistent analysis problem Řešení: zámky (dvoufázový COMMIT)
Zámky z hlediska působnosti na řádcích na tabulkách z hlediska přístupu Sdílené (pro čtení) výhradní = eXkluzivní (pro zápis)
Udílení S a X zámků Matice kompatibility: Zámky na R držené ostatními procesy XS- Nový proces žádá o zámek na R XNNY SNYY -YYY Y – zámek udělen N – zámek neudělen (proces musí čekat)
The lost update problem Proces 1 FETCH R udělen S zámek na R UPDATE R žádá X zámek na R čeká Proces 2 FETCH R udělen S zámek na R UPDATE R žádá X zámek na R čeká ČASČAS Deadlock
The uncommitted dependency problem 1 Proces 1 FETCH R žádá S zámek na R čeká znovuzahájení FETCH R udělen S zámek na R Proces 2 UPDATE R udělen X zámek na R ROLLBACK odemknutí zámku X na R ČASČAS
The uncommitted dependency problem 2 Proces 1 UPDATE R žádá X zámek na R čeká znovuzahájení UPDATE R udělen X zámek na R Proces 2 UPDATE R udělen X zámek na R ROLLBACK odemknutí zámku X na R ČASČAS
The inconsistent analysis problem Proces 1 FETCH R1 (30) suma = 30 udělen S zámek na R1 FETCH R2 (30) žádá S zámek na R2 čeká Proces 2 FETCH R2 (40) udělen S zámek na R2 UPDATE R2 (40 -> 30) udělen X zámek na R2 FETCH R1 (30) udělen S zámek na R1 UPDATE R1 (30 -> 20) žádá X zámek na R1 čeká ČASČAS Deadlock
Dvoufázový COMMIT První fáze: získávání zámků –může být postupné (ne najednou) Druhá fáze: odemykání zámků –většinou najednou pomocí COMMIT nebo ROLLBACK Řeší tři konkurenční problémy, resp. převádí na problém deadlocku
Deadlock Situace, kdy více procesů čeká vzájemně jeden na druhého Proces 1 Proces 2 Proces 3
Deadlock Detekce deadlocku –Detekce cyklu v grafu čekajících procesů –Hlídání doby trvání operace (trvá-li atomární operace příliš dlouho, asi nastal deadlock) Odstranění deadlocku –Vybere se nějaký proces z těch, které jsou v deadlocku a provede se na něm ROLLBACK