Ich möchte ein Skript erstellen, in dem die Oracle-Sitzungen, die in einen Deadlock geraten, automatisch beendet werden
BEARBEITEN Besser erklärt, einige Sätze korrigiert und ein Testfall hinzugefügt, um das Deadlock-Szenario zu demonstrieren.
Warum wollen Sie das Rad neu erfinden? Oracle erkennt automatisch einen Deadlock und löst ORA-00060: deadlock detected while waiting for resource
aus , und setzt eine der an dem Deadlock beteiligten Transaktionen zurück, die Oracle als Opfer bestimmt hat. Die vorherigen erfolgreichen Transaktionen werden nicht rückgängig gemacht. Selbst nach dem Deadlock-Fehler wird die vorherige erfolgreiche Transaktion festgeschrieben, wenn ein Commit ausgegeben wird. Zu diesem Zeitpunkt wird auch die Transaktion der anderen Sitzung erfolgreich sein und Sie können eine Festschreibung ausgeben. Es gibt nichts, was Sie hier explizit tun müssen. Deadlocks werden automatisch gelöscht – Sie müssen sie nie löschen sie.
Normalerweise benötigt Oracle ein oder zwei Sekunden, um einen Deadlock zu erkennen, und gibt den Fehler aus.
Sie können es mit einem einfachen Testfall versuchen, wie hier gezeigt:Grundlegendes zu Oracle Deadlock
Sehen wir uns einen Testfall an -
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
Notieren Sie sich die Zeit jeder Transaktion, ich habe zum besseren Verständnis Zeit auf Zeit eingestellt.
SITZUNG:1
12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;
1 row updated.
Elapsed: 00:00:00.00
SITZUNG: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;
An diesem Punkt wartet SITZUNG 2 weiter .
SITZUNG:1
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
An diesem Punkt, SITZUNG 2 ist das Opfer eines Deadlocks, SITZUNG 1 wartet noch.
Sehen wir uns die Sitzungsdetails von SITZUNG 2 an -
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>
Also v$session
Details, wenn sie in SITZUNG 2 angesehen werden , also SID 14, besagt, dass der Status ACTIVE ist .
Sehen wir uns die Sitzungsdetails einer anderen Sitzung an, nennen wir sie SITZUNG 3 um des willens willen. Denken Sie daran, SITZUNG 1 wartet noch.
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>
Für andere Sitzungen also SITZUNG 2 , also SID 14, ist INAKTIV . SITZUNG 1 WARTET immer noch mit Ereignis enq: TX - row lock contention
.
Lassen Sie uns SITZUNG 2 festlegen -
12:22:18 SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
12:25:43 SQL>
An diesem Punkt wird die Sperre für SITZUNG 1 aufgehoben , lassen Sie uns auch Sitzung 1 festschreiben -
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
zeigt SITZUNG 1 habe so lange bis SITZUNG 2 gewartet wurde begangen.
Zusammenfassend ist hier die gesamte Geschichte von Sitzung 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>
Zusammenfassend ist hier die gesamte Geschichte von Sitzung 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>
Sehen wir uns nun an, welche Transaktion tatsächlich rückgängig gemacht und welche festgeschrieben wurde -
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>
Fazit
Meiner Meinung nach ist der beste Weg, die Sitzungsdetails eines Deadlocks zu erfahren, die Details so ausführlich wie möglich zu protokollieren. Andernfalls ist es für einen DBA ein Albtraum, Nachforschungen anzustellen, ohne dass die richtigen Informationen protokolliert werden. Selbst ein Entwickler würde es als Herkulesaufgabe empfinden, den eigentlichen Designfehler zu beheben und zu beheben, wenn die Deadlock-Fehlerdetails nicht ausführlich protokolliert werden. Und um mit einer einzeiligen Aussage abzuschließen:Ein Deadlock ist auf einen Konstruktionsfehler zurückzuführen, Oracle ist nur das Opfer und die Anwendung der Schuldige. Deadlocks sind beängstigend, aber sie weisen auf Designfehler hin, die früher oder später behoben werden müssen.