LogMiner – Archive Analysis

Buenas a todos.

Neste post vou ensinar como usar o LogMiner para a visualização do conteúdo de RedoLogs e ArchiveLogs.

Vamos primeiro nos ambientar.

Imagine que seu banco de dados está gerando muito archivelog e a partição disponível está enchendo constantemente, ou imagine que seu I/O subiu repentinamente em uma determinada parte do dia e você gostaria de saber o que houve.

Nestes casos, se voce não achou nada na boa e velha V$SQL, você poderá usar o LogMiner.

LogMiner é um pacote com um conjunto de procedures que analisam arquivos de redo e archivedlogs.
Depois de analisado os arquivos, uma tabela é criada com as informações das queries.

Chega de lero lero, vamos à ação.

( para que este tutorial fique mais completo, vou mostrar como pegar um archivedlog de uma base de dados e abrí-lo em outra base de dados. Afinal, você não vai ficar analisando archives em produção, né? )

Passo 1, gerar dicionario de dados no servidor produtivo

Apesar de estranho, precisaremos gerar o dicionário de dados do servidor produtivo para que os archives possam ser lidos no nosso servidor de teste.
Não se preocupe, a geração dos dicionários de dados não vai prejudicar a performance do servidor. ( não vai prejudicar perceptívelmente )

Se você não pegar os dicionários de dados do servidor produtivo e tentar ler os archives diretamente, provavelmente vai se deparar com erros como ORA-01295 ou ORA-01294.

No servidor produtivo execute:

SQL>EXECUTE DBMS_LOGMNR_D.BUILD(OPTIONS=> DBMS_LOGMNR_D.STORE_IN_REDO_LOGS);

PL/SQL procedure successfully completed.

Após executar este comando o Oracle vai gerar um archivedlog com os dados do dicionário.
Para descobrir qual archive pegar, execute esta SQL:

SQL> SELECT NAME FROM V$ARCHIVED_LOG WHERE DICTIONARY_BEGIN='YES';

NAME
----------------------------------------------------------------------------------
/u01/app/oracle/admin/archs/3_6937_703020779.dbf

Passo 2, obter o archived log

Bem, neste passo eu copiei os archivedlogs de um servidor produtivo para minha maquina virtual.
Ahhh, por consequência eu copiei o archive com o dicionário de dados junto!

scp 10.0.0.23:/u01/app/oracle/admin/archs/*.dbf /oracle/MEUS_ARCHIVES

Passo 3, carregando arquivos para o LogMiner.

Agora que já temos o dicionário de dados, fica fácil usar o LogMiner!
Só carregarmos os ArchivedLogs usando a procedure ADD_LOGFILE e iniciarmos o LogMiner com START_LOGMNR…

EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
LOGFILENAME => '/oracle/MEUS_ARCHIVES/1_64530_703020779.dbf',
 OPTIONS => DBMS_LOGMNR.ADDFILE);

EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
LOGFILENAME => '/oracle/MEUS_ARCHIVES/1_64531_703020779.dbf', 
OPTIONS => DBMS_LOGMNR.ADDFILE);

EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
LOGFILENAME => '/oracle/MEUS_ARCHIVES/1_64532_703020779.dbf', 
OPTIONS => DBMS_LOGMNR.ADDFILE);

EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
LOGFILENAME => '/oracle/MEUS_ARCHIVES/1_64533_703020779.dbf',
 OPTIONS => DBMS_LOGMNR.ADDFILE);

EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
LOGFILENAME => '/oracle/MEUS_ARCHIVES/1_64534_703020779.dbf',
 OPTIONS => DBMS_LOGMNR.ADDFILE);

EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
LOGFILENAME => '/oracle/MEUS_ARCHIVES/1_64535_703020779.dbf',
 OPTIONS => DBMS_LOGMNR.ADDFILE);

EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
LOGFILENAME => '/oracle/MEUS_ARCHIVES/1_64536_703020779.dbf',
 OPTIONS => DBMS_LOGMNR.ADDFILE);

EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
LOGFILENAME => '/oracle/MEUS_ARCHIVES/3_6937_703020779.dbf',
 OPTIONS => DBMS_LOGMNR.ADDFILE);

Depois de carregar os arquivos vamos iniciar a “Mineração” heehhehehe

EXECUTE DBMS_LOGMNR.START_LOGMNR(OPTIONS => DBMS_LOGMNR.DICT_FROM_REDO_LOGS);

Passo 4, analisando o resultado do LogMiner…

Depois de esperar uma eternidade para o LogMiner terminar a análise, chegou a hora da tão esperada pesquisa das queries!

SELECT * FROM V$LOGMNR_CONTENTS;

Caso queira, eu uso a seguinte query que abrevia muito o resultado 🙂

set linesize 200;
set pagesize 400;
col REDO format a30;
col UNDO format a30;
col TABLE_SPACE format a20;
col USERNAME format a20;

SELECT
	USERNAME,
	TABLE_SPACE,
	SUBSTR( SQL_REDO, 0, INSTR( SQL_REDO , '"', 1,4)) REDO,
	SUBSTR( SQL_UNDO, 0, INSTR( SQL_UNDO , '"', 1,4)) UNDO
FROM V$LOGMNR_CONTENTS
WHERE SQL_UNDO IS NOT NULL;

Aeee, agora você sabe o que está “Rolando” em seus archives!

Grande abraço!

Deixe uma resposta