DBMS_REPAIR包使用詳解
Oracle提供了DBMS_REPAIR包用來發現、標識並修改資料檔案中的壞塊。
任何工具都不是萬能的,使用這個包的同時會帶來資料丟失、表和索引返回資料不一致,完整性條件約束破壞等其他問題。因此當出現錯誤時,應當首先從物理備份或邏輯備份恢複,使用dbms_repair只是在沒有備份的情況下使用的一種手段,這種方式一般都會造成資料的丟失。
dbms_repair包的工作原理比較簡單,是將檢查到的壞塊標註出來,使隨後的dml操作跳過該塊,同時,dbms_repair包還提供了用於儲存索引中包含的標註為壞塊中的索引值,以及修複freelist和segment bitmap的過程。
有一點需要注意,dbms_repair包沒有進行授權,只有sys使用者可以執行。
下面通過一個例子來簡要介紹一下dbms_repair包的使用。
Oracle 11g 在RedHat Linux 5.8_x64平台的安裝手冊
Linux-6-64下安裝Oracle 12C筆記
在CentOS 6.4下安裝Oracle 11gR2(x64)
Oracle 11gR2 在VMWare虛擬機器中安裝步驟
Debian 下 安裝 Oracle 11g XE R2
一、構造測試環境
首先建立一個測試用資料表空間,由於需要用UtralEdit開啟資料檔案修改部分內容來類比錯誤,因此資料檔案要建的小一些。
SQL> CREATE TABLESPACE TEST DATAFILE 'E:ORACLEORADATATESTTEST.DBF' SIZE 1M
2 EXTENT MANAGEMENT LOCAL AUTOALLOCATE SEGMENT SPACE MANAGEMENT MANUAL;
資料表空間已建立。
SQL> CREATE TABLE TEST (ID NUMBER, NAME VARCHAR2(30)) TABLESPACE TEST;
表已建立。
SQL> INSERT INTO TEST SELECT ROWNUM, OBJECT_NAME FROM DBA_OBJECTS;
已建立6232行。
SQL> COMMIT;
提交完成。
SQL> CREATE INDEX IND_TEST_ID ON TEST (ID);
索引已建立。
SQL> CREATE INDEX IND_TEST_NAME ON TEST (NAME);
索引已建立。
為了確保oracle已經把剛才插入的資料寫到資料檔案中,現在重起資料庫。
SQL> CONN /@TEST AS SYSDBA
已串連。
SQL> SHUTDOWN
資料庫已經關閉。
已經卸載資料庫。
ORACLE 常式已經關閉。
SQL> STARTUP
ORACLE 常式已經啟動。
Total System Global Area 89201304 bytes
Fixed Size 453272 bytes
Variable Size 62914560 bytes
Database Buffers 25165824 bytes
Redo Buffers 667648 bytes
資料庫裝載完畢。
資料庫已經開啟。
二、類比錯誤的產生
用UtralEdit開啟資料檔案,只要修改了資料檔案中任意的一個位置,都會造成資料檔案錯誤。但我們測試需要將錯誤發生位置定位在TEST表中。
SQL> CONN YANGTK/YANGTK@TEST
已串連。
SQL> SELECT SUBSTR(ROWID, 10, 6), ID, NAME FROM TEST WHERE ID = 123;
SUBSTR(ROWID ID NAME
------------ ---------- ------------------------------
AAAAAG 123 ALL_REPCONFLICT
如何在資料檔案中找到TEST表的資料呢?可以通過ROWID來定位的記錄在資料檔案中的位置。任意選擇一條記錄(如上面ID = 123),取得它的ROWID,我們知道,ROWID中10~15位表示這條記錄所在的BLOCK是資料檔案的第幾個BLOCK。
A表示0,B為1,G表示6。這說明這條記錄在資料檔案的第六個block中。
SQL> SHOW PARAMETER DB_BLOCK_SIZE
NAME TYPE VALUE
------------------------------------ ----------- ---------------
db_block_size integer 16384
BLOCK的大小是16k。
SQL> SELECT TO_CHAR(6*16384, 'XXXXXX') FROM DUAL;
TO_CHAR
-------
18000
SQL> SELECT TO_CHAR(7*16384, 'XXXXXX') FROM DUAL;
TO_CHAR
-------
1C000
用UtralEdit開啟資料檔案,將檔案定位18000h處(以二進位方式開啟,如果沒有用二進位開啟,可以使用CTRL+H快速鍵切換)。根據上面的計算,可以得出,我們要找到記錄在18000h和1C000h之間。
Number類型123在資料庫存放方式為03C20218,03表示佔有三位,C2表示最高位是百位,02表示最高位上是1,18表示低位上是23。
具體的數值可以通過下面的查詢得到:
SQL> SELECT DUMP(123) FROM DUAL;
DUMP(123)
---------------------
Typ=2 Len=3: 194,2,24
SQL> SELECT TO_CHAR(194, 'XX'), TO_CHAR(2, 'XX'), TO_CHAR(24, 'XX') FROM DUAL;
TO_ TO_ TO_
--- --- ---
C2 2 18
關於具體的NUMBER類型在資料庫中是如何儲存的,有興趣的可以參閱另一篇文章。
下面使用UtralEdit的搜尋功能,尋找到03C20218,將其修改為03C20216,並儲存。
上面是通過oracle的ROWID在檔案中定位,這相對來說要複雜一些。下面可以使用UtralEdit的功能達到相同的目的。
根據上面的查詢可以得到,ID = 123時,NAME的值是ALL_REPCONFLICT。
下面用UtralEdit開啟檔案,使用CTRL+H方式切換到文字格式設定,直接尋找ALL_REPCONFLICT字串。找到後,CTRL+H切換回二進位格式。向前跳過一個長度位元組(本例中為0F),就可以看到123的值03C20218,進行修改後,儲存並退出。
SQL> SELECT * FROM TEST WHERE ID = 123;
ID NAME
---------- ------------------------------
123 ALL_REPCONFLICT
這時候查詢仍然可以得到正確結果,因為oracle使用了db_cache中的結果。為了讓oracle“看”到修改,必須重起資料庫。
SQL> CONN /@TEST AS SYSDBA
已串連。
SQL> SHUTDOWN
資料庫已經關閉。
已經卸載資料庫。
ORACLE 常式已經關閉。
SQL> STARTUP
ORACLE 常式已經啟動。
Total System Global Area 89201304 bytes
Fixed Size 453272 bytes
Variable Size 62914560 bytes
Database Buffers 25165824 bytes
Redo Buffers 667648 bytes
資料庫裝載完畢。
資料庫已經開啟。
SQL> CONN YANGTK/YANGTK@TEST
已串連。
SQL> SELECT * FROM TEST WHERE ID = 123;
SELECT * FROM TEST WHERE ID = 123
*
ERROR 位於第 1 行:
ORA-01578: ORACLE 資料區塊損壞(檔案號7,塊號6)
ORA-01110: 資料檔案 7: 'E:ORACLEORADATATESTTEST.DBF'
已經類比成功了壞塊,開始進入正題部分,使用DBMS_REPAIR表來處理壞塊。
更多詳情見請繼續閱讀下一頁的精彩內容: