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.