Дек 162011
 

По просьбам трудящихся, оставленным в комментариях к этому посту, решил написать, как анализировать redo logs на другой базе. Здесь подразумевается, что база, с которой мы взяли логи (далее исходная) и та, на которой мы будем их анализировать (далее целевая) одной и той же версии и работают на железе одинаковой архитектуры и на одинаковых ОС.
Такой анализ немного осложняется тем, что на целевой базе скорее всего будут отсутствовать объекты, которые есть на основной и в результате этого в колонках sql_redo и sql_undo представления v$logmnr_contents вместо понятного sql-выражения будет нечто невразумительное, что-то вроде этого:

INSERT INTO Object#2581(col#1, col#2) VALUES (HEXTORAW('4a6f686e20446f65'), HEXTORAW('c306'));

Чтобы избежать подобного эффекта, создаётся так называемый LogMiner dictionary, который может находиться как в отдельном файле, так и быть частью redo log'а.
Итак, у нас есть 2 способа создать словарь:

Словарь в отдельном файле:
  1. Подготовительные шаги на исходной базе
    -- Установим параметр utl_file_dir
    ALTER SYSTEM SET utl_file_dir='/usr/oracle/coredump' SCOPE=SPFILE;
    -- Рестартуем базу, ибо параметр этот на лету менять нельзя
    SHUTDOWN IMMEDIATE;
    STARTUP;
  2. Создаём словарь

    EXEC DBMS_LOGMNR_D.BUILD ('dictionary.ora', 
    			  '/usr/oracle/coredump', 
    			  OPTIONS => DBMS_LOGMNR_D.STORE_IN_FLAT_FILE);

    Во время создания словаря на базе не должно быть никаких DDL-операций, иначе он выйдет нецелостным и DBMS_LOGMNR_D.BUILD упадёт с ошибкой.

  3. Добавляем файлы на целевой базе. Всё просто, как тут
    -- Для первого лога в списке:
    EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
    	LOGFILENAME => '/nfs/testdb_0000231745.log.ora',
    	OPTIONS => DBMS_LOGMNR.NEW);
    -- Для остальных логов в списке:
    EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
    	LOGFILENAME => '/nfs/testdb_0000231746.log.ora',
    	OPTIONS => DBMS_LOGMNR.ADDFILE);
    EXECUTE DBMS_LOGMNR.ADD_LOGFILE( 
    	LOGFILENAME => '/nfs/testdb_0000231747.log.ora',
    	OPTIONS => DBMS_LOGMNR.ADDFILE);
    -- и т.д.
  4. Запускаем сессию Logminer'а

    EXEC DBMS_LOGMNR.START_LOGMNR(DICTFILENAME => '/nfs/dictionary.ora');

    /nfs/dictionary.ora - это и есть наш словарь. Он, как и логи, лежит на исходной базе, просто я расшарил каталог с ними по nfs.

Словарь в логах:
  1. Подготовительные шаги на исходной базе
    -- Включим дополнительное логирование
    -- если этого не сделать, то создать словарь
    -- не получится, будет ошибка
    ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
  2. Запишем словарь в лог
    EXEC DBMS_LOGMNR_D.BUILD (OPTIONS => DBMS_LOGMNR_D.STORE_IN_REDO_LOGS);

    Во время построения словаря, в отличие от первого способа, на базе могут идти DDL-операции, да и сам процесс происходит заметно быстрее. Если словарь не помещается в один лог. он может быть разбит на несколько. Узнать, сколько логов он занимает, можно запросами

    SELECT NAME FROM V$ARCHIVED_LOG WHERE DICTIONARY_BEGIN='YES';
    SELECT NAME FROM V$ARCHIVED_LOG WHERE DICTIONARY_END='YES';
  3. Добавляем файлы на целевой базе - тут всё аналогично способу с файлом
  4. Запускаем сессию Logminer'а
    EXEC DBMS_LOGMNR.START_LOGMNR(OPTIONS => DBMS_LOGMNR.DICT_FROM_REDO_LOGS);

Теперь можно просматривать v$logmnr_contents в поисках нужных данных так же, как и в предыдущем посте про logminer.

По завершению работы не забываем закрыть сессию Logminer'а:

EXEC DBMS_LOGMNR.END_LOGMNR();

ORACLE рекомендует создавать словарь после того, как таблицы и другие объекты уже созданы и до интересующих нас событий, т.к. словарь является моментальным слепком структуры базы данных. Если создать таблицу после создания словаря и попытаться анализировать манипуляции с ней, то удобочитаемого вывода не получится из-за отсутствия её в словаре.

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">

(обязательно)

(обязательно)