Pular para o conteúdo

Solução de Problema de Transação Bloqueada em Banco de Dados Oracle: Como Resolver com Rollback Force

Rollback Force

Galera, uma historinha baseada em fatos reais, com final feliz forçado, rsrs…

Há mais ou menos um mês atras, um dos nossos clientes entrou em contato reclamando que um dos usuários não estava conseguindo usar a aplicação.

O erro retornado era: “ORA-01591 lock held by in doubt distributed transaction”.

Engraçado que ao tentar entrar no sqlplus ou no sqldeveloper (a partir da minha máquina), o mesmo erro aparecia.

Na segunda tentativa, consegui conectar. Porém, ao tentar rodar um script de verificação das sessões, o tal erro de novo:

Bem, tentei entrar localmente, através do sql plus do servidor como sysdba (via Putty)… e não é que o mesmo erro aparece!

Porém, assim como aconteceu com o SqlDeveloper, consegui conectar na segunda tentativa. Como meus scripts não estavam funcionando, tentei dar um select * na v$session… e um erro de arrepiar:

O desespero bateu na porta!

Nesta hora, vi que era o momento de “conversar com o google”. Após pesquisar alguns resultados, testei o seguinte comando:

SQL
select LOCAL_TRAN_ID
from sys.pending_trans$
Order by reco_time;

Mas… não entendi muito do resultado.  Dei um select * nesta tal sys.pending_trans$ , e verifiquei que tinha uma sessão com o status “prepared”

Tentei matar a sessão do usuário “infiliz”,  mas a sessão ficou killed e os erros continuaram.

E se tentarmos matar o processo do usuário pelo unix? Também não deu certo.

Blz… Hora de conversar com o Metalink

Quando a gente estava pensando em restartar o banco, inclusive avisando os poucos usuários que ainda estavam conectados, surge a OTN , e a luz no fim do túnel:

SQL
rollback force

Após este comando,  “só sucesso”! Veja como ficou o status da sessão:

Explicação: O Oracle não conseguiu concluir o recover da transação deste usuário, ficando com esta pendência.  Pelo que eu entendi, houve um corrompimento do dicionário de dados, por isso eu não conseguia estabelecer novas conexões ou fazer consultas simples como um describe.;

Para resolver, era necessário forçar o rollback, uma vez que o Oracle sozinho não estava conseguindo fazer isso. Para fazê-lo:

–  primeiro é necessário verificar o n. da transação a ser feito rollback

SQL
select * From sys.pending_trans$ Order by reco_time;

–  ou

SQL
select LOCAL_TRAN_ID from sys.pending_trans$ Order by reco_time;

–  depois, comando para forçar o rollback

SQL
rollback force 'trans_id_from_result_above';

– exemplo:

SQL
rollback force '72.12.1336947';

col host form a30
col local_tran_id form a15
col global_tran_id form a45

select local_tran_id, global_tran_id, state, mixed, host, commit# from dba_2pc_pending
/

Interessante, não!? O legal foi descobrir que tinha uma dica no fórum do OTN que não tinha no Metalink! Daí a importância dos fóruns.

E assim terminou a nossa história, forçando nosso banco de dados a ter um lindo final feliz!

Glossário

  • OTN – Oracle Technology Network: Site da Oracle voltado para prover serviços e informações à profissionais de TI que trabalham diretamente com a tecnologia Oracle, como DBA’s, desenvolvedores e arquitetos de sistema. Lá é possível encontrar tutoriais, downloads de programas (incluindo o Oracle Database), blogs e fóruns. Todo o DBA deve ter cadastro seu cadastro neste site.

  • Metalink – Site oficial de suporte da Oracle, voltado para quem tem lisença de uso. É neste site onde são diponibilisados os downloads de patches, por exemplo.

lilian

lilian

Comentário(s) da Comunidade

  1. Lilian

    Muito bom!!!
    Parabéns pela resolução do problema e muito obrigado por compartilhar conosco!
    A observação sobre a dica estar no OTN (aberto) e não no Metalink (fechado) também foi muito legal. 😉

  2. Esse erro quando vemos pela 1°vez sempre assusta.
    Mas a resolução é bastante simples.
    Parabéns pela didática.

    Caso ocorra novamente tem casos que també é nescessário fazer o purge da transação.

    Set pagesize0
    Spool gera_kill_lock.sql
    select ‘ rollback force ”’||LOCAL_TRAN_ID||””||’;’ from dba_2pc_pending
    union all
    select ‘ exec dbms_transaction.purge_lost_db_entry’||'(‘||””||LOCAL_TRAN_ID||””||’)’||’;’|| chr(10) ||’ commit ; ‘
    from dba_2pc_pending ;
    @gera_kill_lock.sql

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

plugins premium WordPress