Адміністратору Oracle: Розкриваємо секрети – глибинний аналіз журналів (Mining for Clues)

Використання утиліти Oracle LogMiner для відновлення транзакцій і скасування змін.

Підлога на іншому кінці дроту був розсерджений. Протягом 20 років він був персональним менеджером клієнтки Еллен Сміт. Але сьогодні, коли Еллен прийшла в банк, система повідомила їй, що Пол більше не є її персональним менеджером! Збитий з пантелику і обгрунтовано засмучений, він вимагав роз'яснень.

Джон, головний адміністратор бази даних банку, повинен був діяти не втрачаючи часу. Він швидко виконав запит до таблиці ACCOUNTS (рахунки), який показав, що значення стовпця ACC_MGR_ID (ідентифікатор персонального менеджера) для рахунку 4567 (рахунок Еллен) дорівнює 1, тоді як ідентифікатор Пола – 5. Раніше це значення безумовно було одно 5. Хто міг змінити його і чому? Крім того, окремий запит показав, що Полу був призначений інший клієнт (з номером рахунку 9876), якого Пол не визнає. Чому це сталося, і хто дійсний персональний менеджер рахунку 9876?

"Риття носом" в архівах

Які варіанти має Джон для виправлення ситуації?

Спочатку можна переглянути на сервері бази даних Oracle журнальні дані. Зауважимо, сервер Oracle для кожної зміни, зробленого в базі даних, генерує запису відкоту і повторного виконання. Простими словами, запис відкату містить значення даних, збережені перед зміною, а запис повторного виконання містить значення даних, збережені після зміни.

Коли відбуваються зміни, записи повторного виконання поміщаються в журнальні буфера в системній глобальної галузі (SGA). Потім процес запису в журнал LGWR записує ці записи в оперативний журнал, і, якщо сервер бази даних працює в режимі архівування (ARCHIVELOG), процес архівування ARC0 збереже ці записи в архівному журналі. Призначення цих журнальних записів полягає в тому, щоб гарантувати (У випадку ушкодження бази даних) повторне виконання зроблених раніше операцій. У разі повної втрати бази даних її адміністратор може відновити створену раніше резервну копію бази даних і застосувати всі архівні журнальні файли, згенеровані після створення цієї копії, щоб "хильнути" цю копію на момент відмови.

А як щодо записів відкату? Відповідно до моделі узгодженості читання в СУБД Oracle користувач бачить змінене значення тільки після фіксації цієї зміни, в іншому випадку сервер бази даних повертає попередні (незмінні) значення. Ці попередні значення беруться з сегментів відкоту. Крім того, під час відновлення даних після їх пошкодження сервер бази даних Oracle для підтримки узгодженості і цілісності даних повинен "відкотити" всі зміни, які не були зафіксовані. Ці записи витягуються з сегментів відкоту. Сегменти відкату змінюються також як і інші сегменти бази даних, тому і для них генеруються журнальні записи, які записуються в оперативний журнал, а потім і в архівний.

У результаті оперативний і архівний журнали містять як інформацію відкоту, так і повторного виконання. Адміністратори бази даних можуть використовувати їх для вилучення як старих значень даних, так і нових. Однак формат оперативного та архівної журналів не опублікований і вони не легким для читання. Для читання та пошуку в оперативному і архівному журналах адміністратори баз даних використовують утиліту Oracle LogMiner (Глибинний аналіз журналу). З цією утилітою можна працювати за допомогою поставляється пакету DBMS_LOGMNR, що з'явився в сервері Oracle8 i. У цій статті описано, як використовувати цей потужний інструмент для вирішення простих і не так вже й простих проблем, що виникають при змінах бази даних Oracle.

Починаємо аналіз

Давайте повернемося до проблеми з рахунком пані Сміт. Джон може почати пошук, як і коли було змінено персональний менеджер її рахунку, використовуючи для цього ретроспективні запити до таблиці рахунків, щоб вибрати попередні значення. Технологія виконання ретроспективних операцій (Oracle Flashback) – функціональні засоби сервера Oracle, які дозволяють бачити значення стовпців в деякий момент у минулому, до їх зміни і фіксації.

Однак ретроспективні запити працюють тільки в інтервалі часу, що задається параметром UNDO_RETENTION (збереження інформації в просторі відкоту), значення якого в OLTP-системах часто не перевищує 30 хвилин. У такому випадку ретроспективні запити не знайдуть змін.

Джон може знайти відповідь на дане питання за допомогою утиліти LogMiner, переглядаючи безпосередньо файли оперативного журналу. Кроки для налаштування і використання LogMiner:


  1. Інсталювати пакет DBMS_LOGMNR. Джон інсталював пакет, а потім в утиліті SQL * Plus підключився до системи як користувач SYS і виконав скрипт $ ORACLE_HOME / rdbms / admin / dbmslm.sql.
  2. Надати роль. Потім Джон надає користувачеві, який буде аналізувати журнал, (в даному випадку, самому собі) роль, необхідну для виконання цього пакету:
    GRANT EXECUTE_CATALOG_ROLE TO JOHN;
  3. Створити синонім. Джон створює публічний синонім:
    CREATE PUBLIC SYNONYM DBMS_LOGMNR FOR SYS.DBMS_LOGMNR;

    Ці перші три кроки потрібно виконати тільки один раз.


  4. Визначити область дії аналізу. Помилка, можливо, трапилася зовсім недавно, тому зміна може все ще знаходитися в оперативних журнальних файлах. Так що, на першому проході Джон вирішує аналізувати лише оперативні журнальні файли. Він визначає ці файли, виконуючи наступний запит:
    SELECT distinct member LOGFILENAME FROM V$LOGFILE;

    LOGFILENAME
    _______________________
    /dev/vgredo01/rlog1a
    /dev/vgredo01/rlog1b


    Для бази даних було створено два оперативних журнальних файлу. Джон обмежує область дії аналізу тільки цими файлами:

    BEGIN
    DBMS_LOGMNR.ADD_LOGFILE
    (“/dev/vgredo01/rlog1a”);
    DBMS_LOGMNR.ADD_LOGFILE
    (“/dev/vgredo01/rlog1b”);
    END;

  5. Запустити сеанс утиліти LogMiner і вказати словник даних (каталог). Для запуску сеансу цієї утиліти Джон виконує наступний SQL-код:
    BEGIN
    DBMS_LOGMNR.START_LOGMNR
    (options =>
    dbms_logmnr.dict_from_online_catalog);
    END;

    Використовуючи параметр OPTIONS, він також вказує, щоб при запуску сеансу утиліти LogMiner сервер бази даних Oracle прочитав інформацію словника даних (для перетворення імен об'єктів) з оперативного словника даних.

    Як згадувалося раніше, журнальні записи зберігаються не у вигляді відкритого тексту. Утиліта LogMiner забезпечує їх чіткий висновок, але деякі значення можуть виводитися не схожими на оригінальні об'єкти. Наприклад, імена власників, таблиць і стовпців не записуються в оперативний журнал в тому вигляді, в якому їх вводили користувачі; вони перетворені в шістнадцятковий формат. Наприклад, ім'я таблиці ACCOUNTS може зберігатися як OBJ # 45C1. Щоб зробити журнальні дані більш легкими для читання, Джон може вказати утиліті LogMiner на необхідність перетворення цих значень в більш пізнавані, транслюючи їх по словника даних.


  6. Перевірити вміст. При запуску сеансу утиліти LogMiner заповнюється подання V $ LOGMNR_CONTENTS, в якому Джон може виявити, що ж сталося з рахунком Еллен Сміт. У запитах шукаються користувачі і час будь-яких оновлень таблиці ACCOUNTS. Запит до подання V $ LOGMNR_CONTENTS і його результати показані на лістингу 1. Зауважимо, Джон повинен виконувати запити до цього подання в тому ж самому сеансі, в якому він запустив сеанс утиліти LogMiner. Він шукає тільки оновлення, тому в рядку 6 лістингу 1 він використовує предикат.

На лістингу 1 Джон бачить, що користувач на ім'я JOE (Джо) оновив цю таблицю в 14:16. Стовпці SID і SERIAL # ідентифікують сеанс, в якому працював цей користувач.







Лістинг 1: вилучення інформації з уявлення V $ LOGMNR_CONTENTS.

 SQL> select username, to_char (timestamp, "mm / dd / yy hh24: mi: ss") timestamp,
2 seg_type_name, seg_name, table_space, session # SID, serial #
3 from v$logmnr_contents
4 where table_name = “ACCOUNTS”
5 and seg_owner = “ARUP”
6 and operation = “UPDATE”;

USERNAME TIMESTAMP SEG_TYPE_N SEG_NAME TABLE_SPAC SID SERIAL #
________ __________________ __________ ______________ ________ ____ _____
JOE 01/26/05 14:16:41 TABPART ACCOUNTS, P1 ACC_D1 532 1962
JOE 01/26/05 14:16:41 TABPART ACCOUNTS, P2 ACC_D2 532 1962
JOE 01/26/05 14:16:41 TABPART ACCOUNTS, P3 ACC_D3 532 1962


Інший стовпець цього подання, SESSION_INFO, містить додаткову інформацію про сеанс користувача Джо. У всіх виведених рядках значення стовпця SESSION_INFO були наступними:

login_username=JOE
client_info=
OS_username=jsmoe
Machine_name=ACMENTNYJSMOE
OS_terminal = OS_process_id = 4080:3096 OS_program name = sqlplus.exe

За цією інформацією Джон дізнається, що Джо поновив ряд записів таблиці ACCOUNTS з машини клієнта на ім'я JSMOE, що працювала в мережі ACMENTNY. Остання порція інформації, OS_program name = sqlplus.exe, також містить важливі відомості. Джо використовував утиліту SQL * Plus, тому він, ймовірно, виконав Нерегламентоване оновлення, але Джо – розробник, йому заборонено оновлювати промислову базу даних, крім випадків надзвичайної ситуації. Чому він зробив ці зміни?

У будь-якому випадку Джон повинен знати, що поновив Джо, а також старі значення, збережені перед оновленням. Для пошуку цієї інформації Джон модифікує запит лістингу 1, щоб вибрати два дуже важливих стовпця подання V $ LOGMNR_CONTENTS: стовпець SQL_REDO – показує оператор, який може бути виконаний, щоб викликати те ж саме зміна, зроблене користувачем, і стовпець SQL_UNDO – оператор, який може бути виконаний для скасування зміни. На лістингу 2 показані результати цього модифікованого запиту.







Лістинг 2: висновок вмісту стовпців SQL_UNDO і SQL_REDO.

SQL>  select sql_undo, sql_redo
2 from v$logmnr_contents
3 where table_name = “ACCOUNTS”
4 and seg_owner = “ARUP”
5 and operation = “UPDATE”;

SQL_UNDO SQL_REDO
___________________________-_______________ ___________ ________________________________
update "ARUP". "ACCOUNTS" set "ACC_M update" ARUP "." ACCOUNTS "set" ACC_M
GR_ID "=" 2 "where" ACC_MGR_ID "=" GR_ID "=" 6 "where" ACC_MGR_ID "="
6 "and ROWID =" AAOKdAALAAAGcEAB "2" and ROWID = "AAOKdAALAAAGcEAB"

update "ARUP". "ACCOUNTS" set "ACC_M update" ARUP "." ACCOUNTS "set" ACC_M
GR_ID "=" 1 "where" ACC_MGR_ID "=" GR_ID "=" 6 "where" ACC_MGR_ID "="
6 "and ROWID =" AAAOKdAALAAAGcEAB0 "1" and ROWID = "AAAOKdAALAAAGcEAB0"

update "ARUP". "ACCOUNTS" set "ACC_M update" ARUP "." ACCOUNTS "set" ACC_M
GR_ID "=" 5 "where" ACC_MGR_ID "=" GR_ID "=" 6 "where" ACC_MGR_ID "="
6 "and ROWID =" AAAOKdAALAAAGcEAB5 "5" and ROWID = "AAAOKdAALAAAGcEAB5"


При особистій зустрічі Джо визнає, що він зробив ці зміни. На свій захист, однак, Джо надає вельми розумне пояснення. Дуже важливий клієнт – Еллен Сміт – мала неприємний досвід роботи з її призначеним персональним менеджером і зажадала змінити його. Такі зміни в базі даних зазвичай робляться головним менеджером, але він був відсутній, і новопризначений персональний менеджер подзвонив Джо і попросив "Поворожити" і допомогти йому. Джо зробив це, виконавши наступний оператор:

UPDATE ACCOUNTS
SET acc_mgr_id = 6
WHERE first_name = “Ellen”
AND last_name = “Smith”;

Але Джо не помітив, що цей оператор оновив 340 записів, кожна з яких відповідала клієнтці з ім'ям Еллен Сміт. Джо хотів оновити запис тільки однієї клієнтки, але через необачність оновив 340 записів. Серед порушених була і клієнтка Пола, яка зовсім не хотіла заміни свого персонального менеджера.

Зауважимо, у вищенаведеному прикладі, Джон аналізував оперативні журнальні файли. Проте якби проблема виникла давно, вміст оперативного журналу вже було б перенесено до архівних журнальні файли. У цьому випадку Джон міг би також аналізувати і архівний журнал. Для цього він просто б вказав імена архівних журнальних файлів у викликах процедури DBMS_LOGMNR.ADD_LOGFILE. Частина, що залишилася завдань залишається тієї ж самої. Ці імена можна визначити за поданням словника даних V $ ARCHIVED_LOG.

Скасування змін

Наступне завдання Джона полягає в тому, щоб негайно оновити інші 339 записів, повернувши їх старі значення. Зауважимо, на лістингу 2, текст під заголовком SQL_REDO показує, що було змінено спочатку, а текст під заголовком SQL_UNDO показує оператори, які можуть використовуватися для скасування цих змін. Хоча Джо спочатку використовував тільки один оператор, утиліта LogMiner реконструює оператори для модифікації кожного запису окремо, як це і показано на лістингу. Для відновлення старих ідентифікаторів персональних менеджерів Джон може виконати кожен з операторів, перерахованих під заголовком SQL_UNDO. Це скасує зміни, які зробив Джо.

Зручний висновок

Висновок значень стовпців SQL_UNDO і SQL_REDO на лістингу 2 не дуже легко читати – всі вони видаються в одному рядку. Для вирішення цієї проблеми Джон може використовувати опцію print_pretty_sql. Він також хоче виконати SQL-оператори в циклі PL / SQL, використовуючи динамічний SQL, а цей підхід вимагає, щоб крапка з комою в кінці кожного оператора була вилучена. Це завдання вирішується за допомогою опції no_sql_delimiter.

Джон вирішує запустити сеанс утиліти LogMiner, використовуючи такі опції:

begin
dbms_logmnr.start_logmnr(
options =>
dbms_logmnr.
dict_from_online_catalog +
dbms_logmnr.print_pretty_sql +
dbms_logmnr.no_sql_delimiter
);
end;

Після виконання цього коду текст стовпця SQL_UNDO у запиті лістингу 2 буде виглядати так:

SQL_UNDO
_____________________________
update “ARUP”.”ACCOUNTS”
set
“ACC_MGR_ID” = 2
where
“ACC_MGR_ID” = 6 and
ROWID = “AAOKdAALAAAGcEAB”


Вибірковий

У попередніх розділах ми обговорювали спосіб вилучення SQL-операторів для скасування всіх операцій оновлення таблиці ACCOUNTS. Звичайно, цю таблицю могли також оновлювати й інші користувачі, Джон не хотів б скасовувати їх зміни. Щоб вибирати тільки відповідні оператори, він може фільтрувати вміст подання V $ LOGMNR_CONTENTS, як це показано на лістингу 3.







Лістинг 3: вибірковий висновок з уявлення V $ LOGMNR_CONTENTS.

select
acc_type, first_name, last_name,
dbms_logmnr.mine_value (redo_value, "ARUP.ACCOUNTS.ACC_MGR_ID") new_value,
dbms_logmnr.mine_value (undo_value, "ARUP.ACCOUNTS.ACC_MGR_ID") old_value
from v$logmnr_contents l, accounts a
where table_name = “ACCOUNTS”
and operation = “UPDATE”
and dbms_logmnr.column_present (undo_value, "ARUP.ACCOUNTS.ACC_MGR_ID") = 1
and dbms_logmnr.column_present (redo_value, "ARUP.ACCOUNTS.ACC_MGR_ID") = 1
and a.rowid = l.row_id;

A FIRST_NAME LAST_NAME NEW_VALUE OLD_VALUE
_______________ _____________ _____________ ____________
D Ellen Smith 5 6
M Ellen Smith 5 10
D Ellen Smith 5 7


Уважно розгляньте цей SQL-код. У ньому використовуються додаткові функції пакету DBMS_LOGMNR. Перша функція, MINE_VALUE, вибирає значення зазначеного стовпця, записаного до або після зміни. Наприклад, оператор DBMS_LOGMNR.MINE_VALUE (UNDO_VALUE, "ARUP.ACCOUNTS.ACC_MGR_ID") показує значення стовпця ACC_MGR_ID перед зміною. Якщо параметр UNDO_VALUE змінити на REDO_VALUE, то цей оператор поверне значення після зміни.

Крім того, функція COLUMN_PRESENT повертає 1, якщо значення стовпця існує і 0 у противному випадку. Коли виконується з'єднання з таблицею ACCOUNTS, вона показує інші відповідні деталі рахунків.

Вихідні дані на лістингу 3 показують старі та оновлені значення стовпця ACC_MGR_ID, тип рахунку ACC_TYPE, а також імена та прізвища (стовпці FIRST_NAME і LAST_NAME). Ці дані допомагають Джону миттєво визначити всі пошкоджені дані і спосіб їх виправлення. Використовуючи SQL-оператор, показаний на лістингу 3, Джон може написати простий PL / SQL-код для відновлення початкових значень стовпця ACC_MGR_ID (Вибірково, після перевірки інших стовпців, таких, як ACC_TYPE або FIRST_NAME, як це показано на лістингу 4.







Лістинг 4: PL / SQL-код для виконання операторів розділу SQL_UNDO.

SQL>  begin
2 for undo_rec in (
3 select sql_undo, row_id
4 from v$logmnr_contents
5 where table_name = "ACCOUNTS" and seg_owner = "ARUP" and operation = "UPDATE"
6 and dbms_logmnr.column_present (undo_value, "ARUP.ACCOUNTS.ACC_MGR_ID") = 1
7 and dbms_logmnr.column_present (redo_value, "ARUP.ACCOUNTS.ACC_MGR_ID") = 1
8 )
9 loop
10 begin
11 execute immediate undo_rec.sql_undo;
12 exception
13 when no_data_found then
14 dbms_output.put_line ("RowId" / / undo_rec.row_id / / "Failed.");
15 end;
16 end loop;
17 end;

Віддалений аналіз журналу

Попереднє обговорення показало, як використовувати утиліту LogMiner для аналізу початкової бази даних в промисловому середовищі. Для підвищення безпеки Джон може переслати архівні журнальні файли в іншу базу даних і там виконати аналіз. Сервер цієї віддаленої бази даних не доступна адміністраторам вихідної бази даних, тому цей підхід мінімізує можливості зловмисного адміністратора з видалення слідів свого втручання. Інша перевага видаленого аналізу – відсутність впливу на продуктивність сервера вихідної бази даних.

На поточному установці, однак, є одна невелика проблема, яку Джон спочатку повинен вирішити. У вищеописаному сценарії Джон використовував оперативний словник даних як словника для перетворення шістнадцяткових значень імен об'єктів в журнальних файлу в легким для читання імена. Такий підхід чудово працює, якщо для аналізу використовується вихідна база даних, але у віддаленій базі оперативний словник вихідної бази даних відсутній.

Якщо Джон займається видаленим аналізом журналу, він має два альтернативних варіанти вирішення цієї проблеми:


  1. Він може змусити утиліту LogMiner записати інформацію оперативного словника даних у журнальні файли, які будуть перенесені в архівний журнал і можуть використовуватися у віддаленому сервері.
  2. Він може вивантажити словник даних вихідного сервера в звичайний файл і використовувати його в віддаленому сервері.

Обидва ці варіанти вимагають вивантаження оперативного словника даних або в журнал, або у звичайний файл. Це завдання може бути виконана за допомогою поставляється пакету DBMS_LOGMNR_D. Якщо цей пакет відсутній, Джон може створити його, виконавши скрипти dbmslmd.sql і prvtlmd.sql, що знаходяться в каталозі $ ORACLE_HOME / rdbms / admin.

Якщо Джон вибере перший варіант (приміщення вихідного словника даних у журнальні файли), то він виконає наступний код:

begin
dbms_logmnr_d.build (
options => dbms_logmnr_d.store_in_redo_logs
);
end;

Зауважимо, цей варіант можливий, якщо в сервері бази даних включений режим архівації (archivelog). У цьому режимі словникова інформація записується в оперативні журнальні файли, а потім, природно, і в архівні журнальні файли. Під час підготовки до аналізу Джон пересилає ці архівні файли (використовуючи утиліту передачі файлів, таку, як FTP) і за допомогою процедури add_logfile пакету dbms_logmnr включає їх для використання при аналізі.

Після цього він запускає сеанс утиліти LogMiner, але з трохи іншим параметром:

dbms_logmnr.start_logmnr( options =>
dbms_logmnr.dict_from_redo_logs
);

Якщо Джон обере другий варіант (зберігання словника даних у звичайному файлі), то він вкаже файл, в який буде записано цей новий словник. Для запису у файл використовується пакет UTL_FILE, тому в параметрі ініціалізації UTL_FILE_DIR повинен бути заданий шлях доступу до цього файлу. Якщо це ще не зроблено, Джон вкаже, наприклад, / tmp (в ОС UNIX):

utl_file_dir = “/tmp”

Щоб це зміна почало діяти, Джон перезапустить екземпляр сервера вихідної бази даних, а потім згенерує новий словник, виконавши:

begin
dbms_logmnr_d.build (
dictionary_filename => “ora_dict.txt”,
dictionary_location => “/tmp”
);
end;

Цей код генерує в каталозі / tmp файл ora_dict.txt. Потім Джон пересилає файл / tmp / ora_dict.txt з сервера вихідної бази даних в каталог / tmp віддаленого сервера бази даних і запускає сеанс утиліти LogMiner, виконуючи:

dbms_logmnr.start_logmnr (dictfilename => "/ tmp / ora_dict.txt");

Зверніть увагу на новий параметр dictfilename, який вказує файл зі словником, створений раніше. Немає ніякої необхідності використання параметра OPTIONS, оскільки Джон не читає з оперативних словника даних або журнальних файлів. Він може використовувати параметр OPTIONS, наприклад, для включення форматування SQL-операторів, видалення точок з комою в кінці цих операторів і т.д.

Який підхід краще? У першому підході журнальні файли містять словник даних, тому під час аналізу вони повинні бути доступними. Якщо ви аналізуєте невеликий набір журнальних файлів, то може виявитися незручним включати в цей набір та файли зі словником. У другому підході звичайний файл доступний незалежно від числа використовуваних журнальних файлів. Однак якщо не встановлено параметр ініціалізації UTL_FILE_DIR, цей підхід не буде доступним.

Додаткова журналізація

Давайте розглянемо трохи інший сценарій історії "Персональний менеджер клієнтки Еллен Сміт". Припустимо, таблиця ACCOUNTS секціонованими за діапазоном значень стовпця ACC_MGR_ID, де для кожного значення цього стовпця створюється окрема секція. У цьому випадку, коли Джо оновив стовпець ACC_MGR_ID, рядки були переміщені в іншу секцію. Наприклад, рядок ACC_MGR_ID = 6 перебувала в шостій секції, але коли Джо встановив у цьому стовпці значення 3, рядок перемістилася в третю секцію. Ідентифікатор рядка ROWID заснований на фізичному місцезнаходження рядки, тому в результаті цього фізичного переміщення був змінений ідентифікатор цього рядка.

Як ви повинні діяти у цьому випадку?

Якщо для скасування оновлення ви виконаєте наступний оператор, витягнутий з сеансу утиліти LogMiner (див. лістинг 2):

update "ARUP". "ACCOUNTS" set "ACC_MGR_ID" = "6" where "ACC_MGR_ID" = "3"
and ROWID = “AAAOKeAAcAAAH8MAA7”;

– Він нічого не зможе оновити, тому що цей ідентифікатор ROWID, ймовірно, не відповідає жодному поточному ROWID в даній таблиці. Гірше, він може відповідати ROWID фактичної рядки, але це буде неправильна рядок для оновлення, оскільки, за визначенням, ROWID аналізованої рядки був змінений. Отже, для отримання зміненої рядка ви не можете покладатися на ROWID.




Наступні кроки

ЧИТАЙТЕ більш докладно:
про утиліту LogMiner
про пакет DBMS_LOGMNR


Щоб однозначно ідентифікувати потрібний рядок, слід використовувати первинний ключ таблиці. Але цей ключ за замовчуванням не записується в журнальні файли.

Для запису інформації про первинні ключах журнальні файли потрібно включити режим додаткової журналізації (supplemental logging); в цьому випадку в журнальні файли разом з інформацією про зміни записуються значення додаткових стовпців. Для включення цього режиму слід виконати оператор:

alter database add supplemental log data (primary key) columns;


Зауважимо, цей режим починає діяти тільки після виконання даного оператора; зворотної сили він не має. Якщо б ви виконали цей оператор до внесення початкових змін, ви змогли б аналізувати журнальні файли і бачити на лістингу 2 наступне вміст стовпця SQL_UNDO:

update "ARUP". "ACCOUNTS" set "ACC_MGR_ID" = "6" where "ACC_NO" = "5720"
and "ACC_MGR_ID" = "3" and ROWID = "AAAOKeAAcAAAH8MAA7";

Зверніть увагу, у вмісті стовпця SQL_UNDO на додаток до ідентфікатору ROWID з'явився первинний ключ, ACC_NO, який дозволяє ідентифікувати правильні рядки.

У режимі додаткової журналізації значення первинного ключа допомагають однозначно ідентифікувати рядки. Якщо таблиця не має первинного ключа, Джон може використовувати режим додаткової журналізації всіх стовпців, яка робить рядка унікальними. З іншого боку, запис цієї додаткової інформації призводить до додаткового навантаження на сервер бази даних, впливаючи на продуктивність, тому її важливість потрібно уважно оцінювати.

Висновок

Журнальні файли сервера бази даних Oracle є, без перебільшення, протокол всього, що відбувається всередині сервера бази даних і містять корисну для аналізу інформацію. Утиліта LogMiner – інструмент для вилучення цієї інформації з журнальних файлів і її застосування для ідентифікації користувача транзакцій і навіть для їх скасування.

Арап Нанда (Arup Nanda) (arup@proligence.com) – директор підрозділу проектування та експлуатації баз даних компанії Starwood Hotels and Resorts (White Plains, New York). У 2003 р. він був удостоєний нагороди "Oracle" s DBA of the Year "(адміністратор року баз даних Oracle). Арап – співавтор книги Oracle Privacy Security Auditing (видавництво Rampant TechPress, 2003) -" Засоби аудиту в СУБД Oracle, забезпечують інформаційну безпеку ".

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*