Oracle
 sql >> Database >  >> RDS >> Oracle

Deadlock in Oracle

Voglio creare uno script in cui le sessioni di Oracle che entrano in un deadlock vengono uccise automaticamente

MODIFICA Spiegato in modo migliore, corretto alcune frasi e aggiunto un test case per dimostrare lo scenario di deadlock.

Perché vuoi reinventare la ruota? Oracle rileva automaticamente un deadlock, genera ORA-00060: deadlock detected while waiting for resource e annulla una delle transazioni coinvolte nello stallo che Oracle ha deciso come vittima. Le precedenti transazioni riuscite non vengono annullate. Anche dopo l'errore di deadlock, se viene emesso un commit, verrà eseguito il commit della precedente transazione riuscita. A questo punto, anche la transazione dell'altra sessione avrà esito positivo e potresti emettere un commit. Non c'è niente che devi fare esplicitamente qui. I deadlock vengono automaticamente cancellati:non è mai necessario cancellare loro.

Di solito, Oracle impiega un secondo o due per rilevare un deadlock e genera l'errore.

Puoi provare con un semplice test case come mostrato qui:Capire Oracle Deadlock

Diamo un'occhiata a un test case -

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

Prendi nota dell'ora di ogni transazione, ho impostato il tempo per una migliore comprensione.

SESSIONE:1

12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;

1 row updated.

Elapsed: 00:00:00.00

SESSIONE: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;

A questo punto, la SESSIONE 2 continua ad aspettare .

SESSIONE:1

12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;

A questo punto, SESSIONE 2 è vittima di una situazione di stallo, SESSIONE 1 sta ancora aspettando.

Diamo un'occhiata ai dettagli della sessione di SESSIONE 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>

Quindi, v$session dettagli se visualizzati nella SESSIONE 2 , ovvero SID 14, dice che lo stato è ACTIVE .

Diamo un'occhiata ai dettagli della sessione di un'altra sessione, chiamiamola SESSIONE 3 per il bene. Ricorda, SESSIONE 1 sta ancora aspettando.

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>

Quindi, per le altre sessioni, SESSIONE 2 , ovvero SID 14, è INATTIVO . SESSIONE 1 è ancora IN ATTESA con l'evento enq: TX - row lock contention .

Impegniamo la SESSIONE 2 -

12:22:18 SQL> commit;

Commit complete.

Elapsed: 00:00:00.01
12:25:43 SQL>

A questo punto, il blocco viene rilasciato per la SESSIONE 1 , impegniamo anche la sessione 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 mostra SESSIONE 1 stava aspettando da così tanto tempo fino alla SESSIONE 2 è stato commesso.

Per riassumere, ecco l'intera storia della sessione 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>

Per riassumere, ecco l'intera storia della sessione 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>

Ora, vediamo quale transazione è stata effettivamente annullata e quale impegnata -

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>

Conclusione

A mio parere, il modo migliore per conoscere i dettagli della sessione di un deadlock è registrare i dettagli nel modo più dettagliato possibile. Altrimenti, è un incubo per un DBA indagare senza informazioni adeguate registrate. Del resto, anche uno sviluppatore troverebbe un compito arduo correggere e correggere l'effettivo difetto di progettazione se i dettagli dell'errore di deadlock non vengono registrati in modo dettagliato. E per concludere con un'affermazione di una riga, un punto morto è dovuto a un difetto di progettazione, Oracle è solo la vittima e l'applicazione è il colpevole. I deadlock fanno paura, ma sottolineano i difetti di progettazione che prima o poi devono essere corretti.