Páginas

14 de jan. de 2019

Dropando um objeto diretamente no Dicionário de Dados



Olá pesssoal,

     No artigo de hoje vou mostrar como apagar objetos do Banco de Dados Oracle, excluindo-os diretamente no Dicionário de Dados, ou seja, excluindo os seus metadados que estão presentes em tabelas do Dicionário de Dados, ao invés de executar um comando convencional do tipo DROP <tipo do objeto> <nome do objeto>.

     Resolvi escrever este artigo para compartilhar algo que tive que aprender por minha conta e risco, pois descobri ano passado, algo "bizarro" em um BD de homologação que administro, onde abri um chamado no MOS (My Oracle Support), e o pessoal da Oracle não conseguiu me dar a solução final após 2 meses de atendimento. Sempre falo muito bem do MOS por ele conter uma base de conhecimento muito rica, evitando que quase sempre eu tenha que abrir um chamado ao encontrar um problema, pois normalmente ele já está lá documentado e com o roteiro da solução, mas dessa vez confesso que fiquei decepcionado, pois pagamos caro pelo suporte e não obtive nenhuma solução após 2 meses de atendimento. Reclamei, mas não obtive um retorno com a justificativa da demora. 
   
     O que aconteceu? Em 10/2018 descobri que a trigger de logon de um sistema num BD de homologação não estava disparando as exceções que eram esperadas, e fui investigar o motivo. Nessa investigação descobri que existia outra trigger de logon chamada "TR_LOGON_JDBC", com owner PUBLIC, que estava inválida. Achei muito estranha essa descoberta, pois NÃO EXISTEM TRIGGER PÚBLICAS, muito menos um usuário com nome PUBLIC neste BD. Não sei como conseguiram criar essa trigger. O objeto estava com data de criação igual a 30/10/2013, data em que o Banco de Dados estava ainda na versão 11.2 (agora está na versão 12.2.0.1). Desconfiei que essa trigger pudesse ser a causa do problema, tentei apagá-la, mas não consegui através do método convencional (comando DROP TRIGGER...), então resolvi abrir um chamado no MOS. Depois de algumas semanas, após cansar de esperar pela solução do MOS, resolvi pesquisar um pouco mais e descobri que o problema original não estava ocorrendo por causa da trigger pública inválida, mas ainda assim eu queria apagá-la, portanto, mantive o chamado aberto e continuei cobrando uma resposta da equipe de suporte do MOS.

     Veja na Imagem 01, em uma das evidências que o MOS me pediu, que a "bizarra" trigger pública existia no BD, e veja na Imagem 02, o resultado de algumas tentativas de apagá-la, seguindo orientações do pessoal do MOS.

Imagem 01 - Evidência da existência da trigger pública TR_LOGON_JDBC

Imagem 02 - Resultados da tentativa de apagar a trigger pública TR_LOGON_JDBC

     Após enviar essas evidências, o MOS pediu várias outras, enviou alguns scripts para eu executar, mas nada conseguiu apagar o objeto. Depois de mais de 1 mês de atendimento chegaram à conclusão que o objeto deveria ser apagado diretamente no dicionário de dados, mas para isso a equipe de suporte precisava de uma orientação mais robusta da equipe de desenvolvimento (essas foram as palavras escritas por eles) para evitar possíveis corrompimentos no BD. Concordo com tal orientação, mas o problema maior é que já tinham se passado 2 meses, o chamado já estava configurado com severidade 1, e nada de darem atenção maior ao problema e resolvê-lo definitivamente. Cansei de esperar e decidi eu mesmo tentar resolvê-lo por minha conta e risco. Comuniquei meus superiores e fui ao mão na massa. O procedimento que executei é muito simples, mas eu particularmente nunca o tinha executado e não sabia se ele poderia gerar alguma consequência desastrosa.

     O que fiz para apagar definitivamente o objeto? Apaguei os registros correspondentes ao seu identificador (object_id = 95742) diretamente em algumas tabelas do dicionário de dados, e em seguida limpei a Shared Pool para que o objeto também fosse excluído da SGA. Seguem abaixo os comandos executados:

SQL>   DELETE FROM OBJ$ WHERE OBJ# = 95742;
       DELETE FROM TRIGGER$ WHERE OBJ# = 95742;
       ALTER SYSTEM FLUSH SHARED_POOL;

     Pronto! Testei o BD, fiz as devidas consultas para atestar que o objeto havia sido apagado e nenhum corrompimento ocorreu no BD. Se algum dia precisar fazer algo parecido, estão aí os comandos... lembrando que a tabela do segundo DELETE (TRIGGER$) deverá ser substituída conforme o tipo de objeto a ser excluído. CUIDADO, faça isso por sua conta e risco, e se possível teste antes em um ambiente que não seja o de PRODUÇÃO!

[]s

Nenhum comentário:

Postar um comentário