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';
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
Ótima dica Alex.
ResponderExcluirContudo 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
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...
ResponderExcluir--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...
Muito Bom Alex.
ResponderExcluirPasso a passo, bem didático, perfeito prá quem quiser simular a situação.
Parabéns!