Como descobrir qual linha está gerando deadlock

Bom, esse post vou tentar ser o mais direto possível. Estou fazendo ele para ajudar um amigo que está precisando dessa solução...

Abra duas sessões no Oracle

Primeira sessão
Segunda sessão
create table t1 as select * from estoque3.cocoprnt

update t1 set descricao = 'VEJA BEM' where controle = '01';
update t1 set descricao = 'EU' where controle = '02';
update t1 set descricao = 'VEJA BEM' where controle = '02'; 
update t1 set descricao = 'EU' where controle = '01';

1 - Primeiramente copie alguma tabela. No exemplo estou copiando a tabela de COCOPRNT do usuário ESTOQUE3.
2 – Atualize o controle 01 da primeira sessão;
3 – Atualize o controle 02 da segunda sessão;
4 – Atualize o controle 02 na primeira sessão. A sessão deve ficar suspensa;
5 – Complete a instrução com deadlock atualizando o controle 01 na segunda sessão;

                Deve aparecer uma mensagem ORA-00060. Execute essa consulta:
select value from v$parameter where name like 'background_dump_dest'; 

                Abra o arquivo alert_nomeInstancia.log desse diretório.

                Na parte final do arquivo vai ter o caminho de um arquivo de rastreamento (trace file) gerado pelo Oracle no local onde indica que aconteceu um deadlock.
 
                Agora busque as seguintes informações no arquivo de rastreamento:
Legenda:
object_id = 14467;
rowid = 'AAADiDAABAAAIkCAAB' e 'AAADiDAABAAAIkCAAA'

                Execute essas consultas abaixo e obtenha qual linha da tabela que foi gerado o deadlock...
--para obter o nome do objeto que gerou o lock
select owner,object_name from dba_objects where object_id = 14467;

 --para os registros que gerarão o deadlock
select * from t1 where rowid = 'AAADiDAABAAAIkCAAB';
select * from t1 where rowid = 'AAADiDAABAAAIkCAAA';
 



E era isso...

Fonte: OCA Oracle Database 11g

Comentários

  1. Ótima dica Alex.
    Contudo fiquei com uma dúvida ainda: É possível descobrir o registro que está em lock, (o mesmo que vc identificou) porém sem ter que abrir o arquivo de Trace e a analisar "a olho" o seu conteúdo e "catar" os Rowids manualmente? Ou seja, dá para fazer isso apenas com consultas de banco?

    Outra dúvida: Essa solução é para deadlocks. A mesma solução se aplica para lock simples de registros ?

    Desde já, obrigado pelas dicas.

    André L. Weber

    ResponderExcluir
  2. Bom, você pode fazer todos os updates do exemplo, exceto o ultimo para que não seja gerado o deadlock. Então faça as consultas que seguem...

    --uso essa consulta apenas para ter uma ideia de quem esta em lock
    select * from v$locked_object;

    --agora preciso saber quem está locando quem???
    select l1.sid, ' está bloqueando ', l2.sid
    from v$lock l1, v$lock l2
    where l1.block =1
    and l2.request > 0
    and l1.id1=l2.id1
    and l1.id2=l2.id2;

    --agora preciso obeter o rowid e o nome do objeto em locj
    select do.object_name,
    dbms_rowid.rowid_create (1, ROW_WAIT_OBJ#, ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW#) "ROWID"
    from v$session s, dba_objects do
    where sid=207
    and s.ROW_WAIT_OBJ# = do.OBJECT_ID ;

    --por fim consulto o rowid da tabela que foi mostrada...
    select * from t1 where rowid = 'AAADiDAABAAAIkCAAB';

    Bom, espero ter ajudado...

    ResponderExcluir
  3. Muito Bom Alex.
    Passo a passo, bem didático, perfeito prá quem quiser simular a situação.
    Parabéns!

    ResponderExcluir

Postar um comentário

Postagens mais visitadas deste blog

Função para contar palavra

Script para desabilitar serviços desnecessários no Windows 7