DBMS_REPAIR的使用 (轉載)
Oracle提供了DBMS_REPAIR包用來發現、標識並修改資料檔案中的壞塊。
任何工具都不是萬能的,使用這個包的同時會帶來資料丟失、表和索引返回資料不一致,完整性約束破壞等其他問題。因此當出現錯誤時,應當首先從物理備份或邏輯備份恢復,使用dbms_repair只是在沒有備份的情況下使用的一種手段,這種方式一般都會造成資料的丟失。
dbms_repair包的工作原理比較簡單,是將檢查到的壞塊標註出來,使隨後的dml操作跳過該塊,同時,dbms_repair包還提供了用於儲存索引中包含的標註為壞塊中的鍵值,以及修復freelist和segment bitmap的過程。
有一點需要注意,dbms_repair包沒有進行授權,只有sys使用者可以執行。
下面透過一個例子來簡要介紹一下dbms_repair包的使用。
一、構造測試環境
首先建立一個測試用表空間,由於需要用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表來處理壞塊。
三、使用DBMS_REPAIR包處理壞塊。
1.建立REPAIR_TABLE和ORPHAN_KEY_TABLE表
SQL> BEGIN
2 DBMS_REPAIR.ADMIN_TABLES (
3 TABLE_NAME => 'REPAIR_TABLE',
4 TABLE_TYPE => dbms_repair.repair_table,
5 ACTION => dbms_repair.create_action,
6 TABLESPACE => 'YANGTK');
7 END;
8 /
PL/SQL 過程已成功完成。
SQL> BEGIN
2 DBMS_REPAIR.ADMIN_TABLES (
3 TABLE_NAME => 'ORPHAN_KEY_TABLE',
4 TABLE_TYPE => dbms_repair.orphan_table,
5 ACTION => dbms_repair.create_action,
6 TABLESPACE => 'YANGTK');
7 END;
8 /
PL/SQL 過程已成功完成。
REPAIR_TABLE用來記錄錯誤檢查結果,ORPHAN_KEY_TABLE用來記錄表壞塊中記錄在索引中對應鍵值。
這兩個表的刪除可以透過下列儲存過程完成
BEGIN
DBMS_REPAIR.ADMIN_TABLES (
TABLE_NAME => 'REPAIR_TABLE',
TABLE_TYPE => dbms_repair.repair_table,
ACTION => dbms_repair.drop_action);
END;
/
BEGIN
DBMS_REPAIR.ADMIN_TABLES (
TABLE_NAME => 'ORPHAN_KEY_TABLE',
TABLE_TYPE => dbms_repair.orphan_table,
ACTION => dbms_repair.drop_action);
END;
/
2.使用CHECK_OBJECT過程檢測壞塊。
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 num_corrupt INT;
3 BEGIN
4 num_corrupt := 0;
5 DBMS_REPAIR.CHECK_OBJECT (
6 SCHEMA_NAME => 'YANGTK',
7 OBJECT_NAME => 'TEST',
8 REPAIR_TABLE_NAME => 'REPAIR_TABLE',
9 CORRUPT_COUNT => num_corrupt);
10 DBMS_OUTPUT.PUT_LINE('number corrupt: ' || TO_CHAR (num_corrupt));
11 END;
12 /
number corrupt: 1
PL/SQL 過程已成功完成。
SQL> SELECT OBJECT_NAME, BLOCK_ID, CORRUPT_TYPE, MARKED_CORRUPT,
2 CORRUPT_DESCRIPTION, REPAIR_DESCRIPTION
3 FROM REPAIR_TABLE;
OBJECT_NAM BLOCK_ID CORRUPT_TYPE MARKED_COR CORRUPT_DE REPAIR_DESCRIPTION
---------- ---------- ------------ ---------- ---------- ----------------------
TEST 6 6148 TRUE mark block software corrupt
這裡和oracle文件上面有點出入,根據oracle文件上面介紹MARKED_CORRUPT列的值是FALSE,只有執行了FIX_CORRUPT_BLOCKS過程才會使MARKED_CORRUPT列的值變為TRUE。懷疑oracle在CHECK的同時,自動進行FIX_CORRUPT_BLOCKS的操作。
SQL> DECLARE
2 num_fix INT;
3 BEGIN
4 num_fix := 0;
5 DBMS_REPAIR.FIX_CORRUPT_BLOCKS (
6 SCHEMA_NAME => 'YANGTK',
7 OBJECT_NAME=> 'TEST',
8 OBJECT_TYPE => dbms_repair.table_object,
9 REPAIR_TABLE_NAME => 'REPAIR_TABLE',
10 FIX_COUNT=> num_fix);
11 DBMS_OUTPUT.PUT_LINE('num fix: ' || TO_CHAR(num_fix));
12 END;
13 /
num fix: 0
PL/SQL 過程已成功完成。
果然,執行FIX_CORRUPT_BLOCKS過程發現FIX了0個壞塊,這一步操作可以省略不用執行。
3.使用DUMP_ORPHAN_KEYS過程來儲存壞塊中的索引鍵值。
這時還存在著一個潛在的問題。表出現了壞塊,但是索引沒有損壞,透過表掃描回出現錯誤,但是透過索引掃描,仍然可以返回結果,這會造成資料的不一致性。
SQL> SELECT * FROM YANGTK.TEST WHERE ID = 123;
SELECT * FROM YANGTK.TEST WHERE ID = 123
*
ERROR 位於第 1 行:
ORA-01578: ORACLE 資料塊損壞(檔案號7,塊號6)
ORA-01110: 資料檔案 7: 'E:ORACLEORADATATESTTEST.DBF'
SQL> SELECT ID FROM YANGTK.TEST WHERE ID = 123;
ID
----------
123
透過使用DUMP_ORPHAN_KEYS過程來儲存壞塊中的索引鍵值,這樣當執行完SKIP_CORRUPT_BLOCKS操作後,就可以重新建立索引了。
SQL> DECLARE
2 num_orphans INT;
3 BEGIN
4 num_orphans := 0;
5 DBMS_REPAIR.DUMP_ORPHAN_KEYS (
6 SCHEMA_NAME => 'YANGTK',
7 OBJECT_NAME => 'IND_TEST_ID',
8 OBJECT_TYPE => dbms_repair.index_object,
9 REPAIR_TABLE_NAME => 'REPAIR_TABLE',
10 ORPHAN_TABLE_NAME=> 'ORPHAN_KEY_TABLE',
11 KEY_COUNT => num_orphans);
12 DBMS_OUTPUT.PUT_LINE('orphan key count: ' || TO_CHAR(num_orphans));
13 END;
14 /
orphan key count: 549
PL/SQL 過程已成功完成。
SQL> DECLARE
2 num_orphans INT;
3 BEGIN
4 num_orphans := 0;
5 DBMS_REPAIR.DUMP_ORPHAN_KEYS (
6 SCHEMA_NAME => 'YANGTK',
7 OBJECT_NAME => 'IND_TEST_NAME',
8 OBJECT_TYPE => dbms_repair.index_object,
9 REPAIR_TABLE_NAME => 'REPAIR_TABLE',
10 ORPHAN_TABLE_NAME=> 'ORPHAN_KEY_TABLE',
11 KEY_COUNT => num_orphans);
12 DBMS_OUTPUT.PUT_LINE('orphan key count: ' || TO_CHAR(num_orphans));
13 END;
14 /
orphan key count: 549
PL/SQL 過程已成功完成。
注意對每個索引都要執行DUMP_ORPHAN_KEYS過程。
4.使用REBUILD_FREELISTS過程來修改FREELISTS。
如果壞塊發生在FREELIST列表中的中部,則FREELIST列表後面的塊都無法訪問,在這個例子中,由於是人為產生的錯誤,清楚錯誤的位置不在FREELIST中,因此可以跳過此步驟,一般情況下,無法定位壞塊位置,則需要執行改過程。
SQL> BEGIN
2 DBMS_REPAIR.REBUILD_FREELISTS (
3 SCHEMA_NAME => 'YANGTK',
4 OBJECT_NAME => 'TEST',
5 OBJECT_TYPE => dbms_repair.table_object);
6 END;
7 /
PL/SQL 過程已成功完成。
5.執行SKIP_CORRUPT_BLOCKS過程,是後續DML操作跳過壞塊
SQL> BEGIN
2 DBMS_REPAIR.SKIP_CORRUPT_BLOCKS (
3 SCHEMA_NAME => 'YANGTK',
4 OBJECT_NAME => 'TEST',
5 OBJECT_TYPE => dbms_repair.table_object,
6 FLAGS => dbms_repair.skip_flag);
7 END;
8 /
PL/SQL 過程已成功完成。
SQL> SELECT OWNER, TABLE_NAME, SKIP_CORRUPT FROM DBA_TABLES
2 WHERE OWNER = 'YANGTK';
OWNER TABLE_NAME SKIP_COR
---------------------------- ---------------------------- --------
YANGTK TEST ENABLED
YANGTK TEST1 DISABLED
YANGTK TEST_AAA DISABLED
YANGTK TEST_PART DISABLED
已選擇4行。
6.重建索引
由於資料和索引仍然存在不一致的問題,因此必須重建索引。
SQL> SELECT * FROM YANGTK.TEST WHERE ID = 123;
未選定行
SQL> SELECT ID FROM YANGTK.TEST WHERE ID = 123;
ID
----------
123
SQL> ALTER INDEX YANGTK.IND_TEST_ID REBUILD;
索引已更改。
SQL> SELECT ID FROM YANGTK.TEST WHERE ID = 123;
ID
----------
123
注意一點,重建索引一點要先DROP,然後再CREATE,使用REBUILD的方式,重建的資料來源來自索引,仍然會導致問題的產生。
SQL> DROP INDEX YANGTK.IND_TEST_ID;
索引已丟棄。
SQL> DROP INDEX YANGTK.IND_TEST_NAME;
索引已丟棄。
SQL> CREATE INDEX YANGTK.IND_TEST_ID ON YANGTK.TEST(ID);
索引已建立。
SQL> CREATE INDEX YANGTK.IND_TEST_NAME ON YANGTK.TEST(NAME);
索引已建立。
SQL> SELECT ID FROM YANGTK.TEST WHERE ID = 123;
未選定行
SQL> SELECT MIN(ID) FROM YANGTK.TEST;
MIN(ID)
----------
550
包含ID = 123的塊已經別標識為壞塊。現在可以看到,最小的ID是550,也就是說,這個壞塊中包含了549條記錄。
SQL> SELECT COUNT(*) FROM ORPHAN_KEY_TABLE;
COUNT(*)
----------
1098
繼續查詢ORPHAN_KEY_TABLE表,可以發現,這些記錄的索引(2個)已經被儲存到了ORPHAN_KEY_TABLE表中。
四、恢復資料
使用DBMS_REPAIR包的目的不僅是為了使表重新可以訪問,而且,使用這個包還能在一定程度上恢復被因壞塊而無法讀取的資料。
由於壞塊產生在表上,因此索引是可以訪問,所有被索引的列的資料都可以恢復。遺憾的是,Oracle的文件並沒有給出恢復的方法,我查詢了METALINK和ASKTOM也沒有找到相應的答案,所以,恢復的工作只能靠自己摸索進行。因此,我並不能保證我的方法一定是正確的,如果想將這種方法應用的正式環境中,請慎重考慮,本人不承擔任何責任。:)
言歸正傳,在上面的步驟中,使用DUMP_ORPHAN_KEYS過程儲存了壞塊中的索引鍵值,下面就透過這些儲存的鍵值來進行資料的恢復。
先看一下ORPHAN_KEY_TABLE的表結構:
SQL> DESC ORPHAN_KEY_TABLE
名稱 是否為空? 型別
-------------------------------------- -------- --------------
SCHEMA_NAME NOT NULL VARCHAR2(30)
INDEX_NAME NOT NULL VARCHAR2(30)
IPART_NAME VARCHAR2(30)
INDEX_ID NOT NULL NUMBER
TABLE_NAME NOT NULL VARCHAR2(30)
PART_NAME VARCHAR2(30)
TABLE_ID NOT NULL NUMBER
KEYROWID NOT NULL ROWID
KEY NOT NULL ROWID
DUMP_TIMESTAMP NOT NULL DATE
由於欄位名基本上都是自解釋的,這裡就不在過多描述了,需要說明的是KEYROWID和KEY兩個欄位。
KEYROWID存放的是該索引鍵值對應的表中的rowid,而KEY儲存的就是索引的鍵值。
但是查詢KEY的值發現,並非像想象中一樣,存放的是1、2、3……或ALL_TABLES、ACCESS$……等值,而是以ROWID方式存放的。
SQL> SELECT KEY FROM ORPHAN_KEY_TABLE WHERE INDEX_NAME = 'IND_TEST_ID' AND ROWNUM = 1;
KEY
---------------------------------------------------------------
*BAAAAAACwQL+
SQL> SELECT KEY FROM ORPHAN_KEY_TABLE WHERE INDEX_NAME = 'IND_TEST_NAME' AND ROWNUM = 1;
KEY
---------------------------------------------------------------
*BAAAAAAHQUNDRVNTJP4
這種ROWID格式如何轉化為NUMBER或VARCHAR2型別呢?查詢文件並沒有找到相應的解決方法。
於是抱著嘗試的想法,覺得DUMP一下,看看資料的結構是怎樣的。
SQL> SELECT DUMP(KEY) FROM ORPHAN_KEY_TABLE WHERE INDEX_NAME = 'IND_TEST_ID' AND ROWNUM < 6;
DUMP(KEY)
----------------------------------------------------------------
Typ=208 Len=10: 2,4,0,0,0,0,2,193,2,254
Typ=208 Len=10: 2,4,0,0,0,0,2,193,3,254
Typ=208 Len=10: 2,4,0,0,0,0,2,193,4,254
Typ=208 Len=10: 2,4,0,0,0,0,2,193,5,254
Typ=208 Len=10: 2,4,0,0,0,0,2,193,6,254
這回看到希望了。還記得上面修改資料檔案時123的編碼嗎?是不是和第一個查詢中的結果很相似?
2,4,0,0,0,0前幾位是不變的,最後一位254也是不變的。中間的部分就是有意義的數字了。其中第一個2表示長度是2,193表示最高位是個位,2表示最高位上的值是1,也就是說,第一個鍵值是數字1。
SQL> SELECT DUMP(1) FROM DUAL;
DUMP(1)
------------------
Typ=2 Len=2: 193,2
Oracle把資料在檔案中的儲存格式儲存在ROWID欄位中了。根據這個假設,我們看看字串是不是以同樣方式儲存的。
SQL> SELECT DUMP(KEY) FROM ORPHAN_KEY_TABLE WHERE INDEX_NAME = 'IND_TEST_NAME' AND ROWNUM < 6;
DUMP(KEY)
----------------------------------------------------------------
Typ=208 Len=15: 2,4,0,0,0,0,7,65,67,67,69,83,83,36,254
Typ=208 Len=17: 2,4,0,0,0,0,9,65,71,71,88,77,76,73,77,80,254
Typ=208 Len=23: 2,4,0,0,0,0,15,65,71,71,88,77,76,73,78,80,85,84,84,89,80,69,254
Typ=208 Len=22: 2,4,0,0,0,0,14,65,76,76,95,65,76,76,95,84,65,66,76,69,83,254
Typ=208 Len=17: 2,4,0,0,0,0,9,65,76,76,95,65,80,80,76,89,254
顯然7代表長度,後面跟著的明顯就是ASCII編碼。
SQL> SELECT CHR(65)||CHR(67)||CHR(67)||CHR(69)||CHR(83)||CHR(83)||CHR(36) FROM DUAL;
CHR(65)
-------
ACCESS$
知道這個規律,就可以著手進行恢復了,首先先了一個小程式用來把ROWID型別轉換為NUMBER型別或VARCHAR2型別。
SQL> CREATE OR REPLACE FUNCTION F_DUMP_FROM_ROWID
2 (
3 P_TYPE IN VARCHAR2,
4 P_DUMP_ROWID IN UROWID
5 )
6 RETURN VARCHAR2 AS
7 V_DUMP_ROWID VARCHAR2(1000);
8 V_NUMBER_STR VARCHAR2(1000);
9 V_POSITION NUMBER;
10 V_NUMBER VARCHAR2(2);
11 BEGIN
12 SELECT DUMP(P_DUMP_ROWID, 16, 7) INTO V_DUMP_ROWID FROM DUAL;
13 V_DUMP_ROWID := SUBSTR(V_DUMP_ROWID, INSTR(V_DUMP_ROWID, ',') + 1);
14 V_DUMP_ROWID := SUBSTR(V_DUMP_ROWID, 1, LENGTH(V_DUMP_ROWID) - 3);
15
16 IF P_TYPE = 'VARCHAR2' THEN
17 V_DUMP_ROWID := REPLACE(V_DUMP_ROWID , ',');
18 RETURN(UTL_RAW.CAST_TO_VARCHAR2(V_DUMP_ROWID));
19 ELSIF P_TYPE = 'NUMBER' THEN
20 V_DUMP_ROWID := V_DUMP_ROWID || ',';
21 V_POSITION := INSTR(V_DUMP_ROWID, ',');
22
23 WHILE (V_POSITION != 0) LOOP
24 V_NUMBER := SUBSTR(V_DUMP_ROWID, 1, V_POSITION - 1);
25 V_DUMP_ROWID := SUBSTR(V_DUMP_ROWID, V_POSITION + 1);
26
27 IF V_POSITION = 2 THEN
28 V_NUMBER_STR := V_NUMBER_STR || '0' || V_NUMBER;
29 ELSIF V_POSITION = 3 THEN
30 V_NUMBER_STR := V_NUMBER_STR || V_NUMBER;
31 ELSE
32 RAISE_APPLICATION_ERROR(-20002, 'DUMP ERROR CHECK THE INPUT ROWID');
33 END IF;
34
35 V_POSITION := INSTR(V_DUMP_ROWID, ',');
36 END LOOP;
37
38 V_NUMBER_STR := REPLACE(V_NUMBER_STR , ',');
39
40 RETURN(UTL_RAW.CAST_TO_NUMBER(V_NUMBER_STR));
41 ELSE
42 RAISE_APPLICATION_ERROR(-20001, 'TYPE NOT VALID OR CAN''T TRANSALTE ' || P_TYPE || ' TYPE');
43 END IF;
44 END;
45 /
函式已建立。
測試一下函式的功能。
SQL> SELECT F_DUMP_FROM_ROWID('NUMBER', KEY) FROM ORPHAN_KEY_TABLE
2 WHERE INDEX_NAME = 'IND_TEST_ID' AND ROWNUM < 6;
F_DUMP_FROM_ROWID('NUMBER',KEY)
-------------------------------------------------------------
1
2
3
4
5
SQL> SELECT F_DUMP_FROM_ROWID('VARCHAR2', KEY) FROM ORPHAN_KEY_TABLE
2 WHERE INDEX_NAME = 'IND_TEST_NAME' AND ROWNUM < 6;
F_DUMP_FROM_ROWID('VARCHAR2',KEY)
-------------------------------------------------------------
ACCESS$
AGGXMLIMP
AGGXMLINPUTTYPE
ALL_ALL_TABLES
ALL_APPLY
好了,剩下的事情就簡單了。我們將ORPHAN_KEY_TABLE表中的記錄轉變後,重新插入到TEST表中即可。
SQL> INSERT INTO YANGTK.TEST (ID, NAME)
2 SELECT
3 F_DUMP_FROM_ROWID('NUMBER', A.KEY),
4 F_DUMP_FROM_ROWID('VARCHAR2', B.KEY)
5 FROM ORPHAN_KEY_TABLE A, ORPHAN_KEY_TABLE B
6 WHERE A.KEYROWID = B.KEYROWID
7 AND A.INDEX_NAME = 'IND_TEST_ID'
8 AND B.INDEX_NAME = 'IND_TEST_NAME';
已建立549行。
SQL> SELECT * FROM YANGTK.TEST WHERE ID = 1;
ID NAME
---------- ------------------------------
1 ACCESS$
SQL> SELECT * FROM YANGTK.TEST WHERE ID = 123;
ID NAME
---------- ------------------------------
123 ALL_REPCONFLICT
SQL> COMMIT;
至此,資料恢復已經完成。
最後,需要說明幾點。
我只做了NUMBER型別和VARCHAR2型別的恢復測試,其他型別的恢復還沒有測試,目前我做的函式也只包含了恢復NUMBER和VARCHAR2型別的功能。而且,目前只進行了單列B數索引的恢復,組合索引、BITMAP索引等其它型別索引沒有測試。另外,如果VARCHAR2(CHAR)型別中包含中文,在ZHS16GBK字符集下我測試透過,其他字符集沒有測試,但估計對於一般中文字符集都不會有問題,但是單位元組字符集可能會有問題。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3907/viewspace-1009794/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- DBMS_REPAIR的使用AI
- DBMS_REPAIRAI
- 使用dbms_repair修復塊損壞AI
- DBMS_REPAIR ExamplesAI
- 使用DBMS_REPAIR確定和跳過壞塊AI
- 使用正確的工具(轉載)
- 轉載-oracle Shrink命令的使用Oracle
- DBMS_REPAIR SCRIPT [ID 556733.1]AI
- DBMS_REPAIR修復壞塊AI
- iOS RAC 的使用總結 (轉載)iOS
- VNC的安裝與使用(轉載)VNC
- 淺談LogMiner的使用(轉載)
- DataGridView使用 --轉載View
- excel使用大全_轉載Excel
- DBMS_REPAIR example (Doc ID 68013.1)AI
- [轉載] PyCharm、CLion 的設定和使用PyCharm
- glog 使用教程 轉載
- [轉載]EditPlus使用技巧
- [轉載] 使用Redis的Java客戶端JedisRedisJava客戶端
- SpringMVC-RequestContextHolder的使用 -- 轉載SpringMVCContext
- 【轉載】oracle全文索引的建立和使用Oracle索引
- redis的簡單使用和介紹(轉載)Redis
- 【轉載】MapStruct使用填坑Struct
- 轉載--V$ACTIVE_SESSION_HISTORY檢視的使用Session
- C語言標頭檔案的使用(轉載)C語言
- 菜鳥必看IPC空連線的使用(轉載)
- 使用dul恢復資料(轉載)
- html中a標籤中的onclick和href的使用--轉載HTML
- 【轉載】linux tail命令的使用方法詳解LinuxAI
- XHEditor使用方法文件、XHEditor下載地址(轉載收藏)
- [轉載]使用uiautomator做UI測試UI
- 轉載:使用Log Miner分析Oracle日誌Oracle
- aix下新增ftp使用者(轉載)AIFTP
- 無備份的資料塊損壞恢復辦法 dbms_repairAI
- [轉載] Python日曆模組| 使用示例的weekday()方法Python
- JAVA字串格式化-String.format()的使用 (轉載)Java字串格式化ORM
- initrd的功能(轉載)
- 利用DBMS_REPAIR包檢查以及COPY處理壞塊:AI