Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Deadlocks in Oracle

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.