利用閃回拯救我們的資料(四)

realkid4發表於2011-01-29

閃回機制探討

 

下面我們一起來詳細研究下,drop閃回的原理。首先,我們構建一個適當的實驗環境。

 

 

SQL> conn scott/tiger@orcl;

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0

Connected as scott

 

SQL> col object_name format a25;

SQL> select object_name,object_id,object_type from user_objects;

 

OBJECT_NAME                OBJECT_ID OBJECT_TYPE

------------------------- ---------- -------------------

PK_DEPT                        51150 INDEX

……(篇幅原因,有刪節)

PCK_MYTEST_WORK                52607 PACKAGE BODY

T                              53218 TABLE

SYS_C005520                    53186 INDEX

IND_T_TEST_NAME                53187 INDEX

T_TEST                         53185 TABLE

 

14 rows selected

 

 

實驗環境下,我們存在物件表T,物件編號為53218。對應的段資訊為:

 

SQL> select segment_name, segment_type, tablespace_name, bytes from user_segments where segment_name='T';

 

SEGMENT_NA SEGMENT_TYPE       TABLESPACE_NAME           BYTES

---------- ------------------ -------------------- ----------

T          TABLE              USERS                     65536

 

 

下面,我們嘗試刪除資料表T。

 

SQL> drop table t;

Table dropped

 

SQL> select * from t;

select * from t

 

ORA-00942: 表或檢視不存在

 

 

我們重新查詢物件欄位檢視。

 

SQL> select object_name,object_id,object_type from user_objects;

 

OBJECT_NAME                OBJECT_ID OBJECT_TYPE

------------------------- ---------- -------------------

PK_DEPT                        51150 INDEX

DEPT                           51149 TABLE

EMP                            51151 TABLE

PK_EMP                         51152 INDEX

BONUS                          51153 TABLE

SALGRADE                       51154 TABLE

P_ACCA_LOG_USER_COUNT          52786 PROCEDURE

PCK_MYTEST_WORK                52606 PACKAGE

MY_SEQ                         52578 SEQUENCE

PCK_MYTEST_WORK                52607 PACKAGE BODY

SYS_C005520                    53186 INDEX

IND_T_TEST_NAME                53187 INDEX

T_TEST                         53185 TABLE

BIN$/hWq4qC8ScioKlJiEL1jA      53218 TABLE

w==$0                               

 

 

14 rows selected

 

 

該結果沒有刪節。首先,發現物件T的資訊已經不存在了。其次,一個以BIN$開頭的資料表物件出現在檢視中,而且使用了object_id為53218,與之前T所佔用的object_id相同。接著讓我們檢視段資訊。

 

SQL> col segment_name format a30;

SQL> select segment_name, segment_type, tablespace_name, bytes from user_segments;

 

SEGMENT_NAME                   SEGMENT_TYPE       TABLESPACE_NAME         BYTES

------------------------------ --------------------------------

IND_T_TEST_NAME                INDEX              USERS                 65536

SYS_C005520                    INDEX              USERS                 65536

T_TEST                         TABLE              USERS                 65536

BIN$/hWq4qC8ScioKlJiEL1jAw==$0 TABLE              USERS                 65536

SALGRADE                       TABLE              USERS                 65536

BONUS                          TABLE              USERS                 65536

EMP                            TABLE              USERS                 65536

PK_DEPT                        INDEX              USERS                 65536

DEPT                           TABLE              USERS                 65536

PK_EMP                         INDEX              USERS                 65536

 

10 rows selected

 

 

資料段segment代表了儲存。在資料段中,我們已經找不到資料表T的資訊了。而新新增的BIN$卻還是佔據了一個位置。

 

最後,我們檢查資料表檢視。

 

SQL> select table_name, tablespace_name from user_tables;

 

TABLE_NAME                     TABLESPACE_NAME

------------------------------ ------------------------------

DEPT                           USERS

EMP                            USERS

BONUS                          USERS

SALGRADE                       USERS

T_TEST                         USERS

 

 

資料表T資訊被刪除了,同時那個BIN$物件並沒有被識別為資料表。

 

那麼,回收站檢視的情況呢?

 

SQL> select object_name, original_name, operation, type ,ts_name from user_recyclebin;

 

OBJECT_NAME               ORIGINAL_NAME          OPERATION TYPETS_NAME

------------------------- --------------------------------

BIN$/hWq4qC8ScioKlJiEL1jA T              DROP      TABLE  USERS

w==$0                                                                                          

 

 

user_recyclebin幫助我們揭示了BIN$物件的本來面目。這個物件是記錄原資料庫表T的資訊。

 

到此處,我們的結論也就不難獲得了。所謂的閃回drop,就是一種物件假刪除技術。當系統引數recyclebin被設定為on的時候,Oracle是開啟閃回drop功能的。

 

當對資料表使用drop的時候,Oracle並不是將物件直接刪除,而是採用了物件改名。將刪除的資料表進行改名(邏輯上),改為BIN$開頭的一個編碼。

 

這個編碼佔據了原有資料表的所有資源(包括物件資訊和儲存資訊),但是不能算成為原物件的等價體。也就是說,如果我們直接操作這個修改名,系統會報錯,因為Oracle不認為這個物件是一個資料表。資料表T的資料字典資訊被刪除,而改名的物件資訊沒有加入其中。

 

 

SQL> select * from BIN$/hWq4qC8ScioKlJiEL1jAw==$0;

 

select * from BIN$/hWq4qC8ScioKlJiEL1jAw==$0

 

ORA-00933: SQL 命令未正確結束

 

 

當我們進行flashback table XXX to before drop的時候,Oracle只是將原來的資料表T資訊重新改回,原有空間和資料並沒有改變。

 

 

那麼,這部分被假刪除的資料是不是要佔用原有物件表空間呢?答案是肯定的。就如同Windows回收站在沒有清空的情況下,是同樣消耗資源一樣。Oracle的回收站也有同樣的特性。

 

 

當我們刪除了一個物件,這個物件資訊隱藏咋資料表空間中,物件是佔用空間的。但是,這部分空間的消耗並不計入到表空間容量之中。當表空間分配不足的時候,這部分閃回所用的硬碟空間是可以自動的被回收。作為一般開發人員和管理人員,這部分的操作是Oracle自動完成,相當於透明的操作。

 

 

那麼,有沒有可能因為閃回drop表空間物件引起一些故障問題呢?我們說是可能的。筆者曾經讀到過一篇博文,文章中闡述了這樣的場景(這裡對文章作者表示敬意):

 

資料庫操作程式中,向一個資料表中插入大量的資料,之後報錯:說使用者沒有drop物件許可權。為什麼進行的insert操作,而提示說沒有drop許可權呢?程式使用者也的確是沒有drop許可權。

 

最後發現是表空間中,非recyclebin可用空間使用耗盡,需要回收recyclebin中的空間。在這個過程中,Oracle不是使用直接覆蓋的方法,而是自動生成了drop語句命令(一種遞迴呼叫),刪除那些BIN$物件。在這個過程中,使用到了使用者的drop許可權。

 

解決的方法也很簡單:管理員直接purge空間既可以。

 

 

閃回與安全

 

看了閃回功能,對我們的drop命令也有了一層新的認識。那麼,可能有些應用是需要絕對安全刪除(如PCI中的一項要求!),不希望一些被drop掉的資訊還保留在資料庫中,存在不安全因素。

 

對這種情況,可以使用兩種方法。一個是直接關閉recyclebin引數,設定為off。這樣就關閉了閃回drop的特性了。也就不會出現安全問題。這種方法筆者認為很實用,因為在生產環境下,drop資料表的情況還是比較少的,特別是應用層面。

 

第二個方法就是加引數的drop語句。使用drop table XXX purge,就不會將資料表儲存在回收站中了。

 

SQL> select count(*) from t;

 

  COUNT(*)

----------

         0

 

SQL> drop table t purge;

 

Table dropped

 

SQL> select count(*) from user_recyclebin;

 

  COUNT(*)

----------

         0

 

//物件沒有經過回收站,直接被刪除;

 

 

同時,下面兩個命令比較有用。

 

ü        drop tablespace XXX including contents;刪除表空間的時候,不使用回收站,並連帶清除回收站;

ü        drop user XXX cascade;刪除使用者和對應使用者物件的時候,不使用回收站並連帶清除回收站;

 

 

 

閃回特性

 

在這個系列中,我們介紹了閃回技術中的最常用的兩個分支:閃回查詢和閃回drop。經過我們的分析和討論,可以發現:閃回是一個目標,並不代表一種技術。閃回所提倡的是在我們在進行破壞性操作,並且已經在事務生效之後,希望回到原點的一種快速恢復。在閃回之前,我們可能只能依靠複雜的備份恢復過程來實現這個目標,而有了閃回,這個目標可以輕而易舉的實現。

 

但是,有一點要注意:閃回幾個分支,包括資料庫閃回、閃回查詢和閃回drop都是依靠不同的機制和原理。共同點是實現的目標相同。閃回查詢是利用的undo機制,閃回drop是借用了重新命名和空間自動回收。所以我們在理解這三個分支的時候,要建立相對獨立的知識體系,不要彼此混淆。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-686496/,如需轉載,請註明出處,否則將追究法律責任。

相關文章