Ik wil een script maken waarbij de orakelsessies die in een impasse raken automatisch worden afgebroken
BEWERKEN Op een betere manier uitgelegd, enkele zinnen gecorrigeerd en een testcase toegevoegd om een impassescenario te demonstreren.
Waarom wil je het wiel opnieuw uitvinden? Oracle detecteert automatisch een deadlock, gooit ORA-00060: deadlock detected while waiting for resource
, en draait een van de transacties terug die betrokken waren bij de impasse die Oracle als het slachtoffer besloot. De eerdere succesvolle transacties worden niet teruggedraaid. Zelfs na de deadlock-fout, als een commit wordt uitgegeven, wordt de vorige succesvolle transactie vastgelegd. Op dit moment zal de transactie van de andere sessie ook slagen en kunt u een commit uitgeven. U hoeft hier niets expliciet te doen. Deadlocks worden automatisch opgeheven -- u hoeft nooit te wissen hen.
Gewoonlijk heeft Oracle een seconde of twee nodig om een impasse te detecteren en de fout te veroorzaken.
U kunt het proberen met een eenvoudige testcase, zoals hier wordt gedemonstreerd:Oracle Deadlock begrijpen
Laten we eens naar een testcase kijken -
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
Noteer de tijd van elke transactie, ik heb de tijd op timing ingesteld voor een beter begrip.
SESSIE:1
12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;
1 row updated.
Elapsed: 00:00:00.00
SESSIE: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;
Op dit moment blijft SESSIE 2 wachten .
SESSIE:1
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
Op dit moment, SESSIE 2 is het slachtoffer van een impasse, SESSIE 1 wacht nog steeds.
Laten we eens kijken naar de sessiedetails van SESSIE 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>
Dus, v$session
details wanneer bekeken in SESSIE 2 , d.w.z. SID 14, zegt dat de status ACTIEF is .
Laten we eens kijken naar de sessiedetails van een andere sessie, laten we het SESSIE 3 noemen ter wille. Onthoud, SESSIE 1 wacht nog steeds.
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>
Dus, voor andere sessies, SESSIE 2 , d.w.z. SID 14, is INACTIEF . SESSIE 1 is nog WACHT met gebeurtenis enq: TX - row lock contention
.
Laten we ons inzetten voor SESSIE 2 -
12:22:18 SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
12:25:43 SQL>
Op dit punt wordt de vergrendeling vrijgegeven voor SESSIE 1 , laten we ook sessie 1 vastleggen -
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
toont SESSIE 1 wachtte zo lang op SESSIE 2 werd gepleegd.
Om samen te vatten, hier is het hele verhaal van sessie 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>
Om samen te vatten, hier is het hele verhaal van sessie 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>
Laten we nu eens kijken welke transactie daadwerkelijk is teruggedraaid en welke is vastgelegd -
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>
Conclusie
Naar mijn mening is de beste manier om de sessiedetails van een impasse te kennen, door de details zo uitgebreid mogelijk te loggen. Anders is het een nachtmerrie voor een DBA om te onderzoeken zonder dat de juiste informatie is vastgelegd. Trouwens, zelfs een ontwikkelaar zou het een enorme taak vinden om de eigenlijke ontwerpfout te corrigeren en op te lossen als de details van de impassefout niet uitgebreid worden vastgelegd. En om af te sluiten met een one-liner statement:een impasse is te wijten aan een ontwerpfout, Oracle is slechts het slachtoffer en de applicatie is de boosdoener. Deadlocks zijn eng, maar ze wijzen op de ontwerpfouten die vroeg of laat moeten worden verholpen.