воскресенье, 21 марта 2010 г.

Использование корзины Oracle

Одно из нововведений Oracle 10g это корзина. Эта возможность работает аналогично корзине в OC Windows или Mac OS. В этой статье будет описано, как работать с корзиной.


Содержание
  1. Начало
  2. Удаление версий таблицы
  3. Зависимые объекты
  4. Ограничения
  5. Отключение корзины
  6. Выводы

Начало

Существует два представления корзины: USER_RECYCLEBIN и DBA_RECYCLEBIN. Для удобства синоним RECYCLEBIN указывает на ваш USER_RECYCLEBIN. По умолчанию корзина активирована, но ее можно отключить в инициализационном параметре RECYCLEBIN, на уровне сессии или системы.

Когда корзина активна, любые таблицы, которые вы удаляете, не удаляются полностью, а попадают в корзину. Вместо того что бы удалить таблицу, Oracle переименовывает ее и все связанные объекты (индексы, триггеры, LOB сегменты и т.д.). Дает им системное имя, которое начинается на BIN$.

Например, рассмотрим такую ситуацию:
SQL> CREATE TABLE TEST (COL VARCHAR2(10), CHANGE_DATE DATE);
TABLE created.

SQL> INSERT INTO TEST VALUES ('Версия 1', SYSDATE);
1 row created.

SQL> SELECT * FROM TEST ;
COL                  CHANGE_DATE
-------------        ---------------------------
Версия 1             14:10:03
Если параметр RECYCLEBIN выставлен в значением ON, (по-умолчанию в Oracle 10g он включен), удаление таблицы приведет к ее перемещению в корзину.
SQL>DROP TABLE TEST;
TABLE dropped.

SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 CAN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, DROPTIME 
    3 FROM RECYCLEBIN; 
SQL>
OBJECT_NAME                    ORIGINAL_NAME TYPE  UND PUR  DROPTIME
------------------------------ ------------- ----- --- ---- ---------------
BIN$HGnc55/7rRPgQPeM/qQoRw==$0 TEST          TABLE YES YES  2008-09-24:15:45:22
Таким образом видим, что таблица переименована, все данные которые в ней содержались, по прежнему находятся в ней. Для Oracle это по прежнему, обычная таблица.
SQL> ALTER SESSION SET NLS_DATE_FORMAT='HH24:MI:SS';
Session altered.
SQL> SELECT * FROM "BIN$HGnc55/7rRPgQPeM/qQoRw==$0";
COL                  CHANGE_DATE
-------------        ---------------------------
Версия 1             14:10:03
Поскольку данные все на месте, то не составит труда вернуть из корзины таблицу обратно. Эта операция известна как «flashback drop». Команда FLASHBACK TABLE... TO BEFORE DROP переименовывает таблицу из имени с BIN$ в ее оригинальное имя, в нашем случае TEST.
SQL> FLASHBACK TABLE TEST TO BEFORE DROP;
Flashback complete.

SQL> SELECT * FROM TEST;
COL                  CHANGE_DATE
-------------        ---------------------------
Версия 1             14:10:03

SQL> SELECT * FROM RECYCLEBIN;
no rows selected
Следует помнить, что после удаления таблицы она только переименовывается, но не удаляется физически. Сегменты таблицы, по прежнему, находятся в табличном пространстве, и занимают место. Вы можете удалить объект из корзины восстановив его или удалив из корзины.
SQL>DROP TABLE TEST;
TABLE dropped.

SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 CAN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, DROPTIME 
    3 FROM RECYCLEBIN; 
SQL>
OBJECT_NAME                    ORIGINAL_NAME TYPE  UND PUR  DROPTIME
------------------------------ ------------- ----- --- ---- ---------------
BIN$HGnc55/7rRPgQPeM/qQoRw==$0 TEST          TABLE YES YES  2008-09-24:16:05:54

SQL> PURGE TABLE "BIN$HGnc55/7rRPgQPeM/qQoRw==$0";
TABLE purged.

SQL> SELECT * FROM RECYCLEBIN;
no rows selected
Есть несколько опций удаления. Можно удалить все из USER_RECYCLEBIN используя PURGE RECYCLEBIN; пользователь с привилегиями DBA может удалить все из всех корзин, используя DBA_RECYCLEBIN; и наконец, можно очистить корзину по схеме и пользователю, используя PURGE TABLESPACE USER.

Oracle сохраняет объекты в таблице до тех пор пока вы не удалили их, или в табличном пространстве хватает места, или не превышена квота пользователя. Очистка произойдет одной операцией с текущего момента до тех пор, пока не освободится достаточно места для текущей операции. Если файлы данных табличного пространства с опцией AUTOEXTEND ON, корзина будет очищена до того как сработает автоприращение.

Удаление версий таблицы

Точно так же как в корзине Windows может быть несколько файлов с одинаковым именем и расширением, в корзине Oracle может быть несколько версий таблицы. Создадим и удалим дважды таблицу TEST.
SQL> CREATE TABLE TEST (COL VARCHAR2(10), CHANGE_DATE DATE);
TABLE created.

SQL> INSERT INTO TEST VALUES ('Версия 1', SYSDATE);
1 row created.

SQL>DROP TABLE TEST;
TABLE dropped.

SQL> CREATE TABLE TEST (COL VARCHAR2(10), CHANGE_DATE DATE);
TABLE created.

SQL> INSERT INTO TEST VALUES ('Версия 2', SYSDATE);
1 row created.

SQL>DROP TABLE TEST;
TABLE dropped.

SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 AN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, DROPTIME 
    3 FROM RECYCLEBIN; 
SQL>
OBJECT_NAME                    ORIGINAL_NAME TYPE  UND PUR  DROPTIME
------------------------------ ------------- ----- --- ---- ---------------
BIN$HGnc55/7rRPgQPeM/qQoRw==$0 TEST          TABLE YES YES  2008-09-24:16:05:54
BIN$HGnc55/8rRPgQPeM/qQoRw==$0 TEST          TABLE YES YES  2008-09-24:16:10:54
Сделаем запрос к таблицам, что бы убедится, что они разные:

SQL> SELECT * FROM "BIN$HGnc55/7rRPgQPeM/qQoRw==$0";
COL                  CHANGE_DATE
-------------        ---------------------------
Версия 1             14:10:03

SQL> SELECT * FROM "BIN$HGnc55/8rRPgQPeM/qQoRw==$0";
COL                  CHANGE_DATE
-------------        ---------------------------
Версия 2             15:38:03
Теперь возникает вопрос, какую версию Oracle восстановит при указании FLASHBACK DROP?
SQL> FLASHBACK TABLE TEST TO BEFORE DROP;
Flashback complete.

SQL> SELECT * FROM TEST;
COL    CHANGE_DATE
-------------        ---------------------------
Версия 2           15:38:03
Oracle всегда восстанавливает последнюю по времени версию объекта. Чтобы восстановить более раннюю версию можно указать имя таблицы для восстановления. Сейчас в корзине две версии:
SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 CAN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, DROPTIME 
    3 FROM RECYCLEBIN; 
SQL>
OBJECT_NAME                    ORIGINAL_NAME TYPE  UND PUR  DROPTIME
------------------------------ ------------- ----- --- ---- ---------------
BIN$HGnc55/7rRPgQPeM/qQoRw==$0 TEST          TABLE YES YES  2008-09-24:16:05:54
BIN$HGnc55/8rRPgQPeM/qQoRw==$0 TEST          TABLE YES YES  2008-09-24:16:10:54
Для восстановления первой версии будем использовать имя первого экземляра:
SQL> FLASHBACK TABLE BIN$HGnc55/7rRPgQPeM/qQoRw==$0 TO BEFORE DROP;
Flashback complete.
SQL> SELECT * FROM TEST;
COL                  CHANGE_DATE
-------------        ---------------------------
Версия 1             14:10:03
Вторая версия осталась в корзине:
SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 CAN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, DROPTIME 
    3 FROM RECYCLEBIN; 
SQL>
OBJECT_NAME                    ORIGINAL_NAME TYPE  UND PUR  DROPTIME
------------------------------ ------------- ----- --- ---- ---------------
BIN$HGnc55/8rRPgQPeM/qQoRw==$0 TEST          TABLE YES YES  2008-09-24:16:10:54

Зависимые объекты

В современных базах данных очень редки ситуации, когда таблица существует сама по себе. Как правило, они имеют индексы, триггеры, связи ограничения. Удаление таблицы приводит к удалению всех зависимых объектов. При удалении все объекты, как и таблица, переименовываются, их новое имя начинается так же с BIN$.
SQL> TRANCATE TABLE TEST;
TABLE truncated.

SQL> INSERT INTO TEST VALUES ('Версия 3', SYSDATE);
1 row created.

SQL> CREATE INDEX TEST_COL_IDX ON TEST(COL);
Index created.

SQL> SELECT * FROM TEST;
COL                  CHANGE_DATE
-------------        ---------------------------
Версия 3             16:59:21

SQL>DROP TABLE TEST;
TABLE dropped.

SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 CAN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, DROPTIME 
    3 FROM RECYCLEBIN ORDER BY DROPTIME; 
SQL>
OBJECT_NAME      ORIGINAL_NAME TYPE  UND PUR  DROPTIME
---------------- ------------- ----- --- ---- -------------------
BIN$HGnc55/8rRPg TEST          TABLE YES YES  2008-09-24:16:10:54
QPeM/qQoRw==$0
BIN$HGnc55//rRPg TEST          TABLE YES YES  2006-09-01:17:08:41
QPeM/qQoRw==$0
BIN$HGnc55/+rRPg TEST_COL_IDX  INDEX NO  YES  2006-09-01:17:08:41
QPeM/qQoRw==$0
Представление RECYCLEBIN имеет и другие столбцы, показывающие и связь между TEST и TEST_COL_IDX.

SQL> ALTER SESSION SET NLS_DATE_FORMAT='HH24:MI:SS';

SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 CAN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, DROPTIME, 
    3 BASE_OBJECT, PURGE_OBJECT 
    4 FROM RECYCLEBIN 
    5 ORDER BY DROPTIME; 
SQL>
OBJECT_NAME      ORIGINAL_NAME TYPE  UND PUR  DROPTIME  BASE_OBJECT PURGE_OBJECT
---------------- ------------- ----- --- ---- --------- ----------- ------------
BIN$HGnc55/8rRPg TEST          TABLE YES YES  16:10:54  233032      233032
QPeM/qQoRw==$0
BIN$HGnc55//rRPg TEST          TABLE YES YES  17:08:41  233031      233031
QPeM/qQoRw==$0
BIN$HGnc55/+rRPg TEST_COL_IDX  INDEX NO  YES  17:08:41  233031      233434
QPeM/qQoRw==$0
Колонка PURGE_OBJECT содержит номер самого объекта, BASE_OBJECT содержит номер главного объекта. Таблица TEST имеет номер 233031, базовый объект для нее – тот же самый, т.е. она сама себе базовый объект. Индекс TEST_COL_IDX имеет номер 233434, а базовый объект для него – 233031, таблица TEST.

Если выполнить FLASHBACK TABLE для таблицы TEST, ее индекс будет восстановлен, но Oracle не переименует его обратно в оригинальное имя. У индекса так и останется имя BIB$.
SQL> FLASHBACK TABLE TEST TO BEFORE DROP;
Flashback complete.

SQL> SELECT * FROM TEST;
COL                  CHANGE_DATE
-------------        ---------------------------
Версия 3             16:59:21

SQL> SELECT * INDEX_NAME FROM USER_INDEXES WHERE TABLE_NAME=’TEST’;
INDEX_NAME
------------------------------
BIN$HGnc55/+rRPgQPeM/qQoRw==$0
Скорее всего, Oracle не особо заботится о сохранении оригинального имени индекса. Если сейчас снова удалить копию таблицы TEST, то выяснится, что Oracle «не помнит» оригинального имени индекса.
SQL>DROP TABLE TEST;
TABLE dropped.

SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 CAN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, 
    3 DROPTIME, BASE_OBJECT, PURGE_OBJECT 
    4 FROM RECYCLEBIN 
    5 ORDER BY DROPTIME; 
SQL>
OBJECT_NAME      ORIGINAL_NAME   TYPE  UND PUR  DROPTIME  BASE_OBJECT PURGE_OBJECT
---------------- --------------- ----- --- ---- --------- ----------- ------------
BIN$HGnc55/8rRPg TEST            TABLE YES YES  16:10:54  233032      233032
QPeM/qQoRw==$0
BIN$HGnc55//rRPg TEST            TABLE YES YES  17:08:41  233031      233031
QPeM/qQoRw==$0
BIN$HGnc56AArRPg BIN$HGnc55/+rRP INDEX NO  YES  17:08:41  233031      233434
QPeM/qQoRw==$1
                 gQPeM/qQoRw==$0
Обратите внимание на значения в столбцах CAN_UNDROP и CAN_PURGE (мы их показываем как UND и PUR) для индекса. Индекс не может быть восстановлен без таблицы, значение CAN_UNDROP равно NO. В то же время индекс может быть удален без таблицы.
SQL> PURGE INDEX "BIN$HGnc56AArRPgQPeM/qQoRw==$1";
Index purged.

SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 CAN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, 
    3 DROPTIME, BASE_OBJECT, PURGE_OBJECT 
    4 FROM RECYCLEBIN 
    5 ORDER BY DROPTIME; 
SQL>
OBJECT_NAME      ORIGINAL_NAME   TYPE  UND PUR  DROPTIME  BASE_OBJECT PURGE_OBJECT
---------------- --------------- ----- --- ---- --------- ----------- ------------
BIN$HGnc55/8rRPg TEST            TABLE YES YES  16:10:54  233032      233032
QPeM/qQoRw==$0
BIN$HGnc55//rRPg TEST            TABLE YES YES  17:08:41  233031      233031
QPeM/qQoRw==$0
Сейчас если восстановить таблицу, то она будет восстановлена без индекса
SQL> FLASHBACK TABLE TEST TO BEFORE DROP;
Flashback complete.

SQL> SELECT * FROM TEST;
COL                  CHANGE_DATE
-------------        ---------------------------
Версия 3             16:59:21

SQL> SELECT * INDEX_NAME FROM USER_INDEXES WHERE TABLE_NAME=’TEST’;
no rows selected
Если удалите таблицу со связанными LOB сегментами, то с ними будет подобная ситуация, исключение состоит в том, что они не могут быть независимо удалены, CAN_UNDROP и CAN_PURGE будут выставлены в NO. Если восстановить таблицу то они будут восстановлены вместе с ней, если таблица будет удалена из корзины, то и они будут удалены.

Ограничения

Если удаляется таблица и затем восстанавливается, ссылочная целостность теряется. Для материализованные представлений, если удаляется таблица, все журналы определенные для этой таблицы удаляются без помещения в корзину. Если удаляется базовая таблица, то bitmap индексы не помещаются в корзину. При восстановлении таблицы из корзины индексы не восстанавливаются.

Отключение корзины

Аналогично корзине в Windows, где можно удалить файл, минуя корзину, в Oracle реализован такой же механизм. Для этого в предложении DROP TABLE указывается PURGE.
SQL> PURGE RECYCLEBIN;
Recyclebin purged.

SQL> SELECT * FROM RECYCLEBIN;
no rows selected

SQL> CREATE TABLE NEW_TABLE (COL1 VARCHAR2(10), COL2 VARCHAR2(10));
TABLE created.

SQL> DROP TABLE NEW_TABLE PURGE;
TABLE dropped.

SQL> SELECT * FROM RECYCLEBIN;
no rows selected
Если отключать корзину на уровне сессии, то требуется выполнить предложение ALTER SESSION SET RECYCLEBIN=OFF. Это даст тот же эффект, что и добавление PURGE в предложение DROP TABLE. Но, стоит отметить, что можно использовать FLASHBACK DROP для восстановления объектов, которые были помещены в корзину до того как было выполнено отключение корзины.
SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 CAN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, 
    3 DROPTIME, BASE_OBJECT, PURGE_OBJECT 
    4 FROM RECYCLEBIN 
    5 ORDER BY DROPTIME; 
SQL>
OBJECT_NAME      ORIGINAL_NAME   TYPE  UND PUR  DROPTIME  BASE_OBJECT PURGE_OBJECT
---------------- --------------- ----- --- ---- --------- ----------- ------------
BIN$HGnc56ACrRPg TEST            TABLE YES YES  16:10:54  233032      233032
QPeM/qQoRw==$0

SQL> ALTER SESSION SET RECYCLEBIN=OFF;
Session altered.

SQL> CREATE TABLE TEST (COL VARCHAR2(10), CHANGE_DATE DATE);
TABLE created.

SQL> INSERT INTO TEST VALUES ('Версия 5', SYSDATE);
1 row created.

SQL> DROP TABLE TEST;
TABLE dropped.

SQL> SELECT OBJECT_NAME, ORIGINAL_NAME, TYPE, 
    2 CAN_UNDROP AS “UND”, CAN_PURGE AS “PUR”, 
    3 DROPTIME, BASE_OBJECT, PURGE_OBJECT 
    4 FROM RECYCLEBIN 
    5 ORDER BY DROPTIME; 
SQL>
OBJECT_NAME      ORIGINAL_NAME   TYPE  UND PUR  DROPTIME  BASE_OBJECT PURGE_OBJECT
---------------- --------------- ----- --- ---- --------- ----------- ------------
BIN$HGnc56ACrRPg TEST            TABLE YES YES  16:10:54  233032      233032
QPeM/qQoRw==$0

SQL> FLASHBACK TABLE TEST TO BEFORE DROP;
Flashback complete.

SQL> SELECT * FROM TEST;
COL                  CHANGE_DATE
-------------        ---------------------------
Версия 3             16:59:21

Выводы

Корзина может содержать несколько версий одного объекта.

Oracle восстанавливает объекты по алгоритму LIFO, можно восстановить старейшую версию, с указанием прямого имени объекта. Oracle при удалении основного объекта удаляет и зависимые объекты, при восстановлении зависимые объекты восстанавливаются (за исключением ограничений указанных выше). Для индексов при восстановлении не восстанавливается оригинальное имя. При отключении корзины, возможность восстановить объекты из нее остается, это касается объектов помещенных в корзину до ее отключения.

Источник.

Комментариев нет:

Отправить комментарий