Управління транзакціями з використанням LogMiner і Flashback Data Archive, Інші СУБД, Бази даних, статті

Автор: Аруп Нанда, член-директор Oracle ACE Director ORACLE ACE


У цій статті розповідається, як ідентифікувати і повернутися назад у часі, скасувати певні транзакції та їх залежності.


ІнтерфейсLogMinerвOracle Enterprise Manager


LogMiner – це раніше часто ігнорувалися дуже потужний інструмент в базі даних Oracle. Він призначений для витягання з журнальних (redo log) файлів DML-операторів, тобто оригінальних SQL-пропозицій, які становлять транзакції, а так же SQL, які відкочують транзакції. (Для введення в LogMiner і принципи його роботи раджу звернутися до моєї статті в Oracle Magazine “Mining for Clues” www.oracle.com/technology/oramag/oracle/05-jul/o45dba.html). Цілком ймовірно до цих пір цей потужний інструмент був недооцінений через відсутність простого інтерфейсу. Однак володіє в Oracle Database 11 g графічним інтерфейсом OEM використовує LogMinerдля вилучення транзакцій з журнальних, що робить процес аналізу та відкату транзакцій дивно простим. (Зауваження: як і в попередніх версіях, для виконання добування інформації з журналів можна використовувати в командному рядку пакет DBMS_LOGMNR).


Давайте подивимося, як це робиться. Для задіяння “розкопки даних” (log mining) необхідно включити додаткове журнал для бази даних або, як мінімум, для таблиці. Для виконання рекурсивного відкату транзакцій (Flashback Transaction) потрібно журналювання первинних ключів. Для включення цього механізму для всієї бази даних треба виконати наступні команди:


SQL> alter database add  supplemental log data;
Database altered.

SQL> alter database add supplemental log data (primary key) columns;
Database altered.


Тепер уявімо, що в базі даних додатком були виконані наступні пропозиції:

SQL> insert into res values  (100002,sysdate,12,1);
1 row created.

SQL> commit;
Commit complete.

SQL> update res set hotel_id = 13 where res_id = 100002;
1 row updated.

SQL> commit;
Commit complete.


SQL> delete res where res_id = 100002;
1 row deleted.

SQL> commit;
Commit complete.


Уважно подивимося на ці пропозиції: кожне закінчується оператором фіксації (commit), що означає, кожне речення є транзакцією. Тепер подивимося, як можна проаналізувати транзакції за допомогою LogMiner в Oracle Database 11g Database Control.


На екрані початкової (home) сторінки OEM виберемо закладку Availability.



Наприклад, щоб скасувати вставку, Oracle повинен видати видалення, як показано вище. Якщо клацнути по наступній транзакції (як показано нижче), видно подробиці, що необхідно виконати для її скасування:


Це – загальний прийом. Клацнемо по Submit, і всі ці транзакції будуть відкатані одним махом.


Інтерфейс командного рядка


Що якщо немає доступу до Oracle Enterprise Manager або, може бути, хочеться зробити це через скрипт? Пакет DBMS_FLASHBACK, який вже був доступний в Oracle Database 10g, містить нову процедуру TRANSACTION_BACKOUT. Ця процедура перезавантажена (Overloaded), тому потрібно лише передати значення іменованих параметрами, як показано нижче:


declare
   trans_arr xid_array;
begin
   trans_arr := xid_array(“030003000D040000″,”F30003000D04010”);
   dbms_flashback.transaction_backout (
        numtxns         => 1,
        xids            => trans_arr,
        options         => dbms_flashback.cascade
   );
end;

Тип xid_array так само є нововведенням Oracle Database 11g. Він призначений для передачі ідентифікаторів транзакцій в процедуру.


Інші можливості LogMiner


Якщо ви використовували XMLType, як тип даних, і все ще є безліч причин для використання його в Oracle Database 11g, то ви будете щасливі побачити, що XML-дані так само можуть бути вилучені за допомогою LogMiner. Він показує їх в обох стовпцях – SQL_REDO і SQL_UNDO.
Коли запускається LogMiner, можна встановити опцію SKIP_CORRUPTION, яка пропустить зіпсовані блоки в файлах журналу (redo logs). Тобто, можна врятувати правильні дані з журналів, навіть якщо вони частково зіпсовані. Ось приклад використання поліпшеного синтаксису:


begin
   dbms_logmnr.start_logmnr(
        options => dbms_logmnr.skip_corruption
   ) ;
end;

Архивретроспективныхданных (Flashback Data Archive)


У Oracle9i Database Release 2 була представлена ​​”машина часу” у вигляді Flashback Query, яка дозволяла отримати версію даних до зміни. Наприклад, якщо ви змінили і зафіксували якесь значення з 100 на 200, все одно можна вибрати це значення за дві хвилини до зміни, навіть якщо воно було зафіксовано. Ця технологія використовує дані до їх зміни з сегментів відкоту. В Oracle Database 10g ця можливість була розширена з введенням опції Flashback Versions Query, за допомогою якої можна відстежувати зміни, застосовані до рядка, разом зі змінами, до цих пір присутніми в сегментах відкату.


Тим не менш, є невелика проблема: коли база даних очищається (recycled), дані відкату скидаються і видаляються значення до змін. Навіть якщо база даних не була очищена (not recycled), дані можуть застаріти і бути видалені з сегментів відкоту для звільнення місця під нові зміни.


У зв’язку з тим, що до Oracle Database 11g ретроспективні (flashback) операції грунтувалися на даних відкату, які доступні протягом короткого часу, реально не можна було їх використовувати протягом більшого періоду часу або для записів постійного зберігання, наприклад, для аудиту. В цьому випадку ми використовуємо тригери, щоб на тривалий час зберегти відомості про зміни.


Не сумуйте. В Oracle Database 11g функціональність Flashback Data Archive (архівування ретроспективних даних) поєднує найкраще з двох світів: простоту й міць ретроспективних запитів, які не залежать від швидкоплинної пам’яті типу undo (відкату). Це тому, що Flashback Data Archive записує зміни в місце більш тривалого зберігання, в область Flashback Recovery Area.


First, you create a Flashback Data Archive, as shown below:
Розглянемо приклад. (Зауваження: для роботи Flashback Data Archive необхідно активувати механізм Automatic Undo Management). По-перше, створимо Flashback Data Archive, як показано нижче:


SQL> create flashback archive near_term
  2  tablespace far_near_term
  3  retention 1 month
  4  /
 
Flashback archive created.

На час проігноруємо значення терміна “retention”, повернемося до цього пізніше. Архів створюється в табличному просторі far_near_term. (Це місце, де зберігаються зміни).


Уявімо, що необхідно записувати зміни в таблиці TRANS. Все, що потрібно зробити, щоб почався запис змін в цей архів, – включити для таблиці статус Flashback Data Archive.


SQL> alter table trans flashback archive near_term;
Table altered.

За цією командою таблиця переводиться в режим Flashback Data Archive. Всі зміни рядків тепер записуються для постійного зберігання. Продемонструємо це.


Для початку виберемо конкретну рядок з таблиці:


SQL> select txn_amt from trans where trans_id = 2;
 
   TXN_AMT
———-
  19325.67
 
SQL> update trans set txn_amt = 2000 where trans_id = 2;
1 row updated.
 
SQL> commit;
Commit complete.

Тепер, якщо вибрати цей рядок, вона завжди покаже 2000 в стовпці. Для того, щоб знайти старе значення на певний момент часу, слід використовувати ретроспективний запит:


select txn_amt
from trans
as of timestamp to_timestamp (“07/18/2007 12:39:00″,”mm/dd/yyyy hh24:mi:ss”)
where trans_id = 2;
 
   TXN_AMT
———-
  19325.67

Далі по закінченні якогось часу, коли дані відкату будуть видалені з undo-сегментів, ще раз виберемо дані ретроспективним запитом:


select txn_amt
from trans
as of timestamp to_timestamp (“07/18/2007 12:39:00″,”mm/dd/yyyy hh24:mi:ss”)
where trans_id = 2;

Результат поверне 19325.65. Даних з undo-сегментів пішли, так звідки ж результат?


Давайте запитаємо у Oracle. Для цього скористаємося авто-трасуванням (autotrace) і подивимося на план виконання:


SQL> set autotrace traceonly explain
SQL> select txn_amt
  2  from trans
  3  as of timestamp to_timestamp (“07/18/2007 12:39:00″,”mm/dd/yyyy hh24:mi:ss”)
  4  where trans_id = 2;
 
Execution Plan
———————————————————-
Plan hash value: 535458644
 
———————————————————-
 
/ Id  / Operation                 / Name               / Rows  / Bytes / Cost (%CPU)/ Time     / Pstart/ Pstop
————————————————————————————————-
/   0 / SELECT STATEMENT          /                    /     2 /    52 /    10  (10)/ 00:00:01 /       /
/   1 /  VIEW                     /                    /     2 /    52 /    10  (10)/ 00:00:01 /       /
/   2 /   UNION-ALL               /                    /       /       /            /          /       /
/*  3 /    FILTER                 /                    /       /       /            /          /       /
/   4 /     PARTITION RANGE SINGLE/                    /     1 /    52 /     3   (0)/ 00:00:01 /     1 /     1
/*  5 /      TABLE ACCESS FULL    / SYS_FBA_HIST_68909 /     1 /    52 /     3   (0)/ 00:00:01 /     1 /     1
/*  6 /    FILTER                 /                    /       /       /            /          /       /
/*  7 /     HASH JOIN OUTER       /                    /     1 /  4053 /    10  (10)/ 00:00:01 /       /
/*  8 /      TABLE ACCESS FULL    / TRANS              /     1 /    38 /     6   (0)/ 00:00:01 /       /
/   9 /      VIEW                 /                    /     2 /  8030 /     3   (0)/ 00:00:01 /       /
/* 10 /       TABLE ACCESS FULL   / SYS_FBA_TCRV_68909 /     2 /  8056 /     3   (0)/ 00:00:01 /       /
————————————————————————————————-
 
Predicate Information (identified by operation id):
—————————————————
 
   3 – filter(NULL IS NOT NULL)
   5 – filter(“TRANS_ID”=2 AND “ENDSCN”>161508784336056 AND “ENDSCN”<=1073451 AND (“STARTSCN” 
               IS NULL OR “STARTSCN”<=161508784336056))
   6 – filter(“F”.”STARTSCN”<=161508784336056 OR “F”.”STARTSCN” IS NULL)
   7 – access(“T”.ROWID=(“F”.”RID”(+)))
   8 – filter(“T”.”VERSIONS_STARTSCN” IS NULL AND “T”.”TRANS_ID”=2)
  10 – filter((“ENDSCN” IS NULL OR “ENDSCN”>1073451) AND (“STARTSCN” IS NULL 
                OR “STARTSCN”<1073451))
 
Note
—–
   – dynamic sampling used for this statement

Це відповідає на запитання “Звідки беруться дані?”: Вони йдуть з таблиці SYS_FBA_HIST_68909, яка знаходиться під Flashback Archive, який раніше був визначений для цієї таблиці. Можна перевірити цю таблицю, однак Oracle не підтримує читання таких даних безпосередньо. У будь-якому випадку я не бачу причин, чому ви не можете зробити цього.


Дані в архіві зберігаються, але як довго? Тут саме місце, щоб вступив в гру термін зберігання. Дані зберігаються аж до закінчення цього періоду. Після цього у міру надходження нових даних старі стираються. Ви можете і самі стерти їх, наприклад:

alter flashback archive near_term purge before scn 1234567;

Управління ретроспективними архівами


В архів можна додати більше одного табличного простору. І навпаки, їх можна видалити звідти. Якщо планується використання табличного простору, який містить інші дані користувача, існує ризик його переповнення даними Flashback Data Archive і нестачі місця під дані користувачів. Щоб знизити цей ризик, слід встановити квоту, скільки місця архів може зайняти в табличному просторі. Квоту можна встановити так:


alter flashback archive near_term modify tablespace far_near_term quota 10M;


Запитуючи подання словника, можна перевірити, для яких таблиць включений Flashback Data Archive:


SQL> select * from  user_flashback_archived_tables;

TABLE_NAME OWNER_NAME FLASHBACK_ARCHIVE_NAME
———- ———- ————————
TRANS      ARUP       NEAR_TERM


Отримати інформацію про архіви можна шляхом запиту до представлення словника:


sql> select * from  flashback_archives;

FLASHBACK_ARCHI FLASHBACK_ARCHIVE# RETENTION_IN_DAYS  PURGE_SCN STATUS
————— —————— —————– ———- ——-
NEAR_TERM                        1                30    1042653
MED_TERM                         2               365    1042744
LONG_TERM                        3              1825    1042838


Використання декількох архівів дає можливість творчо підійти до різних ситуацій. Наприклад, база даних готелю потребує даних про бронювання протягом року, а про платежі – протягом трьох років. Значить, можна визначити кілька архівів з різним політиками зберігання та призначити їх таблиць. Або ж, якщо застосовується стандартна політика зберігання, можна визначити один архів і призначити його архівом за замовчуванням.
alter flashback archive near_term set default;


Коли необхідність у архіві відпаде, його можна вимкнути командою:

alter table trans no flashback archive;

Як бачите, тільки що ви отримали потужну систему зберігання змін без написання навіть одного рядка коду.


Відмінності від стандартного аудиту
Чим відрізняється Flashback Data Archive від стандартного аудиту? По-перше, останній потребує встановлення параметра бази даних audit_trail в значення DB або DB_EXTENDED, а траса (trails) записується в таблицю AUD $, розташовану в табличному просторі SYSTEM. Flashback Data Archives може бути визначений в будь-якому табличному просторі (або більше ніж в одному, так само як і в табличному просторі, що містить дані користувача) і тому може розташовуватися на більш дешевому пристрої зберігання.
По-друге, аудит заснований на автономних транзакції, які мають деякі накладні витрати в плані продуктивності. Flashback Data Archives написаний у вигляді окремого фонового процесу FBDA, тому в цьому випадку вплив на продуктивність менше.
На закінчення, Flashback Data Archives може автоматично регулярно очищатися. Журналами же аудиту необхідно управляти вручну.


Приклади використання
Flashback Data Archive зручний у багатьох випадках. Ось деякі ідеї:



Висновок


Помилки трапляються, однак тепер ви можете авторитетно стверджувати, що зможете ідентифікувати конкретні зміни, що спричинили помилки. І у вас є інструменти для цілісного відкату цих змін, використовуючи скасування транзакцій. Більше ви не обмежені витяганням змін тільки з архівованих і оперативних журналів; зміни записані на необмежений термін у Flashback Archive. Тепер ви можете проводити аудит змін таблиць для всіляких цілей у Flashback Recovery Area, використовуючи лише кілька команд.

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


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

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

Ваш отзыв

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

*

*