Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Deadlocks no Oracle


Eu quero fazer um script onde as sessões oracle que entram em deadlock são mortas automaticamente

EDITAR Explicado de uma maneira melhor, corrigindo algumas frases e adicionando um caso de teste para demonstrar o cenário de impasse.

Por que você quer reinventar a roda? O Oracle detecta um impasse automaticamente, lança ORA-00060: deadlock detected while waiting for resource , e reverte uma das transações envolvidas no impasse que a Oracle decidiu como vítima. As transações anteriores bem-sucedidas não são revertidas. Mesmo após o erro de deadlock, se um commit for emitido, a transação anterior bem-sucedida será confirmada. Neste momento, a transação da outra sessão também será bem-sucedida e você poderá emitir um commit. Não há nada que você precise fazer explicitamente aqui. Os impasses são eliminados automaticamente -- você nunca precisa limpar eles.

Normalmente, o Oracle leva um ou dois segundos para detectar um deadlock e lança o erro.

Você pode tentar com um caso de teste simples, conforme demonstrado aqui:Entendendo o Oracle Deadlock

Vejamos um caso de teste -
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

Observe o tempo de cada transação, defini o tempo no tempo para uma melhor compreensão.

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

1 row updated.

Elapsed: 00:00:00.00

SESSÃO: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;

Neste ponto, a SESSÃO 2 continua esperando .

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

Neste ponto, SESSÃO 2 é vítima de impasse, SESSÃO 1 ainda está esperando.

Vejamos os detalhes da sessão da SESSÃO 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>

Então, v$session detalhes quando visualizados na SESSÃO 2 , ou seja, SID 14, informa que o status é ATIVO .

Vamos ver os detalhes da sessão de outra sessão, vamos chamá-la de SESSÃO 3 por amor. Lembre-se, SESSÃO 1 ainda está esperando.
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>

Então, para outras sessões, SESSÃO 2 , ou seja, SID 14, está INATIVO . SESSÃO 1 ainda está AGUARDANDO com evento enq: TX - row lock contention .

Vamos cometer a SESSÃO 2 -
12:22:18 SQL> commit;

Commit complete.

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

Neste ponto, o bloqueio é liberado para SESSÃO 1 , vamos confirmar a sessão 1 também -
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 SESSÃO 1 estava esperando tanto tempo até a SESSÃO 2 foi cometido.

Para resumir, aqui está toda a história da sessão 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>

Para resumir, aqui está toda a história da sessão 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>

Agora, vamos ver qual transação realmente foi revertida e qual foi confirmada -
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>

Conclusão

Na minha opinião, a melhor maneira de conhecer os detalhes da sessão de um deadlock é registrar os detalhes o mais detalhado possível. Caso contrário, é um pesadelo para um DBA investigar sem as informações apropriadas registradas. Por falar nisso, mesmo um desenvolvedor acharia uma tarefa hercúlea corrigir e corrigir a falha de design real se os detalhes do erro de deadlock não forem registrados detalhadamente. E para concluir com uma declaração de uma linha, Um impasse é devido a uma falha de design, O Oracle é apenas a vítima e o aplicativo é o culpado. Os impasses são assustadores, mas apontam as falhas de design que devem ser corrigidas mais cedo ou mais tarde.