Pular para o conteúdo

Transações pendentes em ambiente distribuído.

Técnica de como eliminar transações pendentes em ambiente Oracle de bases distribuídas.Olá,

Vamos tocar num assunto interessante, as transações pendentes quando se trabalhar com banco de dados em ambientes distribuídos. Essas transações é uma forma de comunicação entre bases de dados Oracle, atráves de DBLINKS, e trabalham com uma tecnologia de controle chamada TWO-PHASE Commit, traduzida, Comprometimento em duas fases, que server como garantia de integridade entre as bases oracle, tanto na base de origem e destino, permitindo que a transação seja segura e íntegra.

A tecnologia de TWO-PHASE Commit, basicamente surgiu para controlar e monitorar as atividades de commit e rollback das transações em ambientes de bases de dados distribuídos, que como dito acima, serve para garantir a consistência dos dados. Existe desde a versão 8i um processo de plano de fundo (background process) chamado RECO, que sua principal função no banco de dados é monitorar todas essas transações, a partir de um LOCAL_TRAN_ID (na base de origem) e um GLOBAL_TRAN_ID (na base de destino) e dizer ao banco de dados, qual é o estado das transações, e se tiver algum problema, tentar recuperar-las.

Junto a com tecnologia, o dicionário de dados ganhou duas visões, a primeira é a dba_2pc_pending, que tem como objetivo listar todas as transações que estão pendentes no banco de dados, que por algum motivo o RECO não fez a sua recuperação ou se a transação ainda está sendo efetivada ou não no banco de dados, e temos também a visão dba_2pc_neighbors, que lista todas as entradas e saídas das transações que estão pendentes, qual o banco de dados, usuário e etc.

O objetivo desse post não é aprensetar a tecnologia TWO-PHASE Commit que é velha, desde 1980 está implementado nos banco de dados Oracle, e sim, de como eliminar essas transações que ficam “pressas” em nossos banco de dados.

Abaixo, segue um exemplo de um ambiente real de como as duas visões acima podem nos auxiliar na eliminação das transações, veja:

SQL> l
   1* select local_tran_id, global_tran_id, state, fail_time, force_time from dba_2pc_pending
 SQL> /
LOCAL_TRAN_ID          GLOBAL_TRAN_ID                           STATE            FAIL_TIM FORCE_TI
 ---------------------- ---------------------------------------- ---------------- -------- --------
 14.28.232339           PARA.WORLD.0964cc71.14.28.232339         collecting       30/07/08
 4.26.229018            PARA.WORLD.0964cc71.4.26.229018          collecting       31/07/08
 12.42.248854           PARA.WORLD.0964cc71.12.42.248854         collecting       11/08/08
SQL> l
   1* select local_tran_id, in_out, database, dbuser_owner from dba_2pc_neighbors
 SQL> /
LOCAL_TRAN_ID          IN_ DATABASE             DBUSER_OWNER
 ---------------------- --- -------------------- ------------------------------
 14.28.232339           in                       ARA_VE_WANDERSON
 14.28.232339           in  PARA.WORLD           DPD
 4.26.229018            in                       ARA_VE_SANSAO
 12.42.248854           in                       ARA_VE_MELQUESEDETE
 14.28.232339           out PEL_DIST_ARA.WORLD   DPD
 14.28.232339           out PEL_DIST_GOI.WORLD   DPD
 4.26.229018            out PEL_DIST_GOI.WORLD   DPD
 12.42.248854           out PEL_DIST_GOI.WORLD   DPD

Perceba que as duas visões podem nos fornecer ótimas informações sobre as pendências que estão no banco de dados, o que nós iremos precisar é apenas o LOCAL_TRAN_ID, que é a identificação da transação distribuída e a partir dessa transação, saber qual é o seu status, pela coluna STATE.

Observe que no primeiro SELECT na visão dba_2pc_pending, a transação de id 14.28.232339 está com seu status de COLLECTING (Coletando) e até agora está um zumbi dentro do banco de dados, pois basta observar pela data de FAIL_TIME (Data de Falha) que o processo RECO não conseguiu fazer sua recuperação até o momento. Então, devemos eliminar-la manualmente, habilitando no banco de dados, a opção de recuperação distribuída, deste modo:

C:\>sqlplus /nolog
SQL*Plus: Release 10.2.0.1.0 - Production on Seg Ago 11 14:21:50 2008
Copyright (c) 1982, 2005, Oracle.  All rights reserved.
SQL> conn sys@pel_dist_ara as sysdba
 Informe a senha:
 Conectado.
 SQL> alter system enable distributed recovery;
Sistema alterado.
SQL> select local_tran_id, global_tran_id, state, fail_time, force_time from dba_2pc_pending;
LOCAL_TRAN_ID          GLOBAL_TRAN_ID                           STATE            FAIL_TIM FORCE_TI
 ---------------------- ---------------------------------------- ---------------- -------- --------
 14.28.232339           PARA.WORLD.0964cc71.14.28.232339         collecting       30/07/08
 4.26.229018            PARA.WORLD.0964cc71.4.26.229018          collecting       31/07/08
 12.42.248854           PARA.WORLD.0964cc71.12.42.248854         collecting       11/08/08
SQL> exec dbms_transaction.purge_lost_db_entry ('14.28.232339');
Procedimento PL/SQL concluído com sucesso.
SQL> commit;
Commit concluído.
SQL> select local_tran_id, global_tran_id, state, fail_time, force_time from dba_2pc_pending;
LOCAL_TRAN_ID          GLOBAL_TRAN_ID                           STATE            FAIL_TIM FORCE_TI
 ---------------------- ---------------------------------------- ---------------- -------- --------
 4.26.229018            PARA.WORLD.0964cc71.4.26.229018          collecting       31/07/08
 12.42.248854           PARA.WORLD.0964cc71.12.42.248854         collecting       11/08/08

Eu também utilizei o pacote DBMS_TRANSACTION, o seu procedimento PURGE_LOST_DB_ENTRY, que é utilizado nesses casos para a eliminação de transações pendentes sem nenhum comprometimento do ambiente oracle.

E sempre que for utilizar essa técnica para eliminar transação pendente, sempre se lembre de duas coisas:

  1. Sempre deverá executar as ações acima com um usuário com permissão de SYSDBA, ou com o usuário SYS, com a role SYSDBA.
  2. Para habilitar a recuperação de transação, podemos utilizar o seguinte comando:

alter system enable distributed recovery;

Para as versões 9i, que foi o começo dos segmentos de UNDO (nosso velho amigo rollback), devemos alterar o seguinte parâmetro da instância:

alter system set “_smu_debug_mode”=4;

É um parâmetro não documentado do banco de dados, que é limpar as transações que estão utilizando os segmentos de UNDO, isso foi corrigido na versão 10g posteriormente.

Após a realização de todas as tarefas acima, poderá ver que o processo RECO não está gerando mais traces no diretório do BACKGROUND_DUMP_DEST das transações que não conseguiu recuperar.

Isso é uma técnica muito utilizada quando queremos eliminar essas transações para evitar lock-held ou incosistência nos dados, mas lembre-se, sempre veja a coluna FAIL_TIME para ver desde quando não está conseguindo efetuar a recuperação, pois a dba_2pc_pending também informa as transações que estão pendentes no dia. Tome cuidado.

Abraços

Rodrigo Almeida

Rodrigo Almeida

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