Chci vytvořit skript, kde se relace orákula, která uvíznou na mrtvém bodě, automaticky zabijí
UPRAVIT Vysvětleno lepším způsobem, opraveno několik vět a přidán testovací případ, který demonstruje scénář uváznutí.
Proč chcete znovu vynalézat kolo? Oracle automaticky detekuje zablokování a vyvolá ORA-00060: deadlock detected while waiting for resource
a vrátí zpět jednu z transakcí zapojených do patové situace, o které se Oracle rozhodl jako o oběti. Předchozí úspěšné transakce nebudou vráceny zpět. I po chybě uváznutí, pokud je vydáno potvrzení, bude předchozí úspěšná transakce potvrzena. V tomto okamžiku bude transakce druhé relace také úspěšná a můžete vydat potvrzení. Není zde nic, co byste museli výslovně dělat. Zablokování se automaticky odstraní – nikdy je nemusíte vymazat je.
Oracle obvykle trvá sekundu nebo dvě, než detekuje uváznutí a vyvolá chybu.
Můžete to zkusit pomocí jednoduchého testovacího případu, jak je ukázáno zde:Understanding Oracle Deadlock
Podívejme se na testovací případ -
SQL> CREATE TABLE t_test(col_1 NUMBER, col_2 NUMBER);
Table created
SQL> INSERT INTO t_test VALUES(1,2);
1 row inserted
SQL> INSERT INTO t_test VALUES(3,4);
1 row inserted
SQL> COMMIT;
Commit complete
SQL> SELECT * FROM t_test;
COL_1 COL_2
---------- ----------
1 2
3 4
Poznamenejte si čas každé transakce, pro lepší pochopení jsem nastavil čas na časování.
SESSION:1
12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;
1 row updated.
Elapsed: 00:00:00.00
REZACE:2
12:16:04 SQL> UPDATE t_test SET col_1 = 6 WHERE col_2=4;
1 row updated.
Elapsed: 00:00:00.00
12:16:31 SQL> UPDATE t_test SET col_1 = 7 WHERE col_2=2;
V tuto chvíli SEKCE 2 stále čeká .
SESSION:1
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
V tuto chvíli REZACE 2 je obětí uváznutí, SESSION 1 stále čeká.
Podívejme se na podrobnosti relace z SEKCE 2 -
12:22:15 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe';
SID STATUS PROGRAM SQL_ID STATE WAIT_CLASS BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- --------------- ----------- ----------------------------------------------------------------
14 ACTIVE sqlplus.exe 60qmqpmbmyhxn WAITED SHORT TIME Network NOT IN WAIT SQL*Net message to client
134 ACTIVE sqlplus.exe 5x0zg4qwus29v WAITING Application VALID enq: TX - row lock contention
Elapsed: 00:00:00.00
12:22:18 SQL>
Takže v$session
podrobnosti při zobrazení v RELACI 2 , tj. SID 14, říká, že stav je AKTIVNÍ .
Podívejme se na detaily relace z jiné relace, nazvěme ji REZACE 3 V zájmu. Pamatujte, REZACE 1 stále čeká.
SQL> set time on timing on
12:24:41 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe'
SID STATUS PROGRAM SQL_ID STATE WAIT_CLASS BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- ---------- ----------- ------------------------------
13 ACTIVE sqlplus.exe 60qmqpmbmyhxn WAITED SHORT TIME Network NOT IN WAIT SQL*Net message to client
14 INACTIVE sqlplus.exe WAITING Idle NO HOLDER SQL*Net message from client
134 ACTIVE sqlplus.exe 5x0zg4qwus29v WAITING Applicatio VALID enq: TX - row lock contention
n
Elapsed: 00:00:00.01
12:24:44 SQL>
Takže pro ostatní relace, REZACE 2 , tj. SID 14, je NEAKTIVNÍ . REZACE 1 stále ČEKÁ s událostí enq: TX - row lock contention
.
Pojďme se zavázat k RELACI 2 -
12:22:18 SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
12:25:43 SQL>
V tomto okamžiku je zámek uvolněn pro RELACI 1 , spusťme také relaci 1 -
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
1 row updated.
Elapsed: 00:08:27.29
12:25:43 SQL> commit;
Commit complete.
Elapsed: 00:00:00.00
12:26:26 SQL>
Elapsed: 00:08:27.29
ukazuje RELACI 1 čekal tak dlouho do REZE 2 byl spáchán.
Abychom to shrnuli, zde je celý příběh relace 1 -
12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;
1 row updated.
Elapsed: 00:00:00.00
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
1 row updated.
Elapsed: 00:08:27.29
12:25:43 SQL> commit;
Commit complete.
Elapsed: 00:00:00.00
12:26:26 SQL>
Abychom to shrnuli, zde je celý příběh ze zasedání 2 -
12:16:04 SQL> UPDATE t_test SET col_1 = 6 WHERE col_2=4;
1 row updated.
Elapsed: 00:00:00.00
12:16:31 SQL> UPDATE t_test SET col_1 = 7 WHERE col_2=2;
UPDATE t_test SET col_1 = 7 WHERE col_2=2
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:00:24.47
12:22:15 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe';
SID STATUS PROGRAM SQL_ID STATE WAIT_CLASS BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- --------------- ----------- ----------------------------------------------------------------
14 ACTIVE sqlplus.exe 60qmqpmbmyhxn WAITED SHORT TIME Network NOT IN WAIT SQL*Net message to client
134 ACTIVE sqlplus.exe 5x0zg4qwus29v WAITING Application VALID enq: TX - row lock contention
Elapsed: 00:00:00.00
12:22:18 SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
12:25:43 SQL>
Nyní se podívejme, která transakce byla skutečně odvolána a která byla potvrzena -
12:25:43 SQL> select * from t_test;
COL_1 COL_2
---------- ----------
5 2
8 4
Elapsed: 00:00:00.00
12:30:36 SQL>
Závěr
Podle mého názoru je nejlepším způsobem, jak zjistit podrobnosti relace o uváznutí, zaznamenat podrobnosti co nejpodrobněji. Jinak je pro DBA noční můra vyšetřovat bez řádných zaznamenaných informací. Pokud na to přijde, dokonce i vývojář by zjistil, že je to otřesný úkol opravit a opravit skutečnou chybu návrhu, pokud podrobnosti o chybě uváznutí nejsou zaznamenány podrobně. A na závěr prohlášením jednoho řádku:Zablokování je způsobeno chybou v designu, Oracle je pouze obětí a aplikace je viníkem. Zablokování je děsivé, ale upozorňuje na konstrukční nedostatky, které je třeba dříve nebo později napravit.