轉---DBMS_ROWID.ROWID_CREATE來解決壞塊
所有的ORACLE文件在提到HINT時,都會指出,HINT的優先順序最高。但是今天卻發現了意外情況。
今天開發人員報告測試庫出現一個錯誤:
ORA-01578: ORACLE data block corrupted (file # 39, block # 24961)
ORA-01110: data file 39: '/oracle/oradata/test/ndmain09.dbf'
由於是測試庫,因此沒有做熱備。測試庫中的資料本身並不很重要,丟失一個BLOCK的資料是可以接受的。所以打算直接丟棄壞塊中的資料。
由於沒有必要嘗試修復資料,沒有必要使用DBMS_REPAIR包,利用設定EVENT匯出的方式又相對比較麻煩,打算採用最簡單的利用ROWID繞過壞塊的方式來重建表。
首先,找到有問題的表:
SQL> SELECT SEGMENT_TYPE, OWNER, SEGMENT_NAME FROM DBA_EXTENTS
2 WHERE FILE_ID = 39
3 AND 24961 BETWEEN BLOCK_ID AND BLOCK_ID+BLOCKS -1 ;
SEGMENT_TYPE OWNER SEGMENT_NAME
------------------ ------------------------------ ------------------------------
TABLE DATA CAT_ZONE_PRODUCT
下面構造壞塊的ROWID:
SQL> CONN DATA
Enter password:
Connected.
SQL> SELECT DATA_OBJECT_ID FROM USER_OBJECTS WHERE OBJECT_NAME = 'CAT_ZONE_PRODUCT';
DATA_OBJECT_ID
--------------
54649
SQL> SELECT DBMS_ROWID.ROWID_CREATE(1, 54649, 39, 24961, 0) FROM DUAL;
DBMS_ROWID.ROWID_C
------------------
AAANV5AAnAAAGGBAAA
我們已經找到壞塊的ROWID了,下面只需要將除了這個BLOCK以外的資料讀出來就可以了:
SQL> CREATE TABLE CAT_ZONE_PRODUCT_BAK AS
2 SELECT /* ROWID(CAT_ZONE_PRODUCT) */ * FROM CAT_ZONE_PRODUCT
3 WHERE ROWID < CHARTOROWID('AAANV5AAnAAAGGBAAA')
4 OR ROWID >= CHARTOROWID('AAANV5AAnAAAGGCAAA')
5 ;
CREATE TABLE CAT_ZONE_PRODUCT_BAK AS
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 39, block # 24961)
ORA-01110: data file 39: '/oracle/oradata/test/ndmain09.dbf'
奇怪,明明已經通過提示告訴Oracle跳過壞塊了,怎麼還報這個錯誤呢?看看執行計劃吧:
SQL> EXPLAIN PLAN FOR
2 SELECT /* ROWID(CAT_ZONE_PRODUCT) */ * FROM CAT_ZONE_PRODUCT
3 WHERE ROWID < CHARTOROWID('AAANV5AAnAAAGGBAAA')
4 OR ROWID >= CHARTOROWID('AAANV5AAnAAAGGCAAA')
5 ;
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 164K| 1175M| 1985 |
| 1 | TABLE ACCESS FULL | CAT_ZONE_PRODUCT | 164K| 1175M| 1985 |
--------------------------------------------------------------------------
Note: cpu costing is off, PLAN_TABLE' is old version
9 rows selected.
SQL> ALTER SESSION SET OPTIMIZER_MODE = FIRST_ROWS;
Session altered.
SQL> EXPLAIN PLAN FOR
2 SELECT /* ROWID(CAT_ZONE_PRODUCT) */ * FROM CAT_ZONE_PRODUCT
3 WHERE ROWID < CHARTOROWID('AAANV5AAnAAAGGBAAA')
4 OR ROWID >= CHARTOROWID('AAANV5AAnAAAGGCAAA')
5 ;
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 164K| 1175M| 1985 |
| 1 | TABLE ACCESS FULL | CAT_ZONE_PRODUCT | 164K| 1175M| 1985 |
--------------------------------------------------------------------------
Note: cpu costing is off, PLAN_TABLE' is old version
9 rows selected.
SQL> ALTER SESSION SET OPTIMIZER_MODE = CHOOSE;
Session altered.
看來HINT沒有起左右,可是從語法上看是沒有任何問題的。難道是or的問題:
SQL> EXPLAIN PLAN FOR
2 SELECT /* ROWID(CAT_ZONE_PRODUCT) */ * FROM CAT_ZONE_PRODUCT
3 WHERE ROWID < CHARTOROWID('AAANV5AAnAAAGGBAAA')
4 ;
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 84208 | 602M| 1985 |
| 1 | TABLE ACCESS BY ROWID RANGE| CAT_ZONE_PRODUCT | 84208 | 602M| 1985 |
-------------------------------------------------------------------------------
Note: cpu costing is off, PLAN_TABLE' is old version
9 rows selected.
這回結果對了,看來果然是or出的問題,不過既然HINT的優先順序最高,為什麼加上一個OR的條件,就導致Oracle的執行計劃改變了呢,看來不是HINT優先順序最高是有疑問的,就是這裡出現了bug。
問題找到了,剩下的就簡單了,將查詢語句簡單變形,再次執行:
SQL> CREATE TABLE CAT_ZONE_PRODUCT_BAK AS
2 SELECT /* ROWID(CAT_ZONE_PRODUCT) */ * FROM CAT_ZONE_PRODUCT
3 WHERE ROWID < CHARTOROWID('AAANV5AAnAAAGGBAAA')
4 UNION ALL
5 SELECT /* ROWID(CAT_ZONE_PRODUCT) */ * FROM CAT_ZONE_PRODUCT
6 WHERE ROWID >= CHARTOROWID('AAANV5AAnAAAGGCAAA')
7 ;
Table created.
SQL> TRUNCATE TABLE CAT_ZONE_PRODUCT DROP STORAGE;
Table truncated.
SQL> INSERT INTO CAT_ZONE_PRODUCT SELECT * FROM CAT_ZONE_PRODUCT_BAK;
157186 rows created.
SQL> COMMIT;
Commit complete.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22907091/viewspace-743055/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- oracle壞塊問題的解決Oracle
- ORA-01578壞塊解決方法
- 資料庫壞塊解決案例一則資料庫
- oracle壞塊問題及解決辦法Oracle
- ORACLE壞塊總結(轉)Oracle
- ORA-01578 壞塊原因模擬及解決方法
- Oracle資料庫壞塊(corruption)-物理壞塊Oracle資料庫
- BIOS被病毒破壞了的解決方法(轉)iOS
- Oracle上的邏輯壞塊和物理壞塊Oracle
- oracle壞塊(二)Oracle
- 一次壞塊的處理過程 [轉]
- ReiserFS檔案系統壞塊的處理(轉)
- ORA-01578(資料塊損壞)跳過壞塊
- 資料塊損壞ORA-1578(發現損壞塊)
- ORA-00600: internal error code, arguments: [kcratr_scan_lastbwr]邏輯壞塊解決ErrorAST
- EXP匯出ORA-01578(資料塊損壞)錯誤解決方法
- Oracle壞塊處理Oracle
- oracle壞塊Block CorruptionsOracleBloC
- rootvg壞塊處理
- 檢查 oracle 壞塊Oracle
- ORACLE 壞塊處理Oracle
- 處理塊損壞
- RMAN修復壞塊
- 轉載:Oracle資料塊損壞恢復總結Oracle
- undo表空間出現壞塊導致資料庫重啟問題解決資料庫
- ORACLE壞塊總結2Oracle
- oracle 壞塊問題急救Oracle
- 壞塊標記並skip
- 如何查詢損壞塊
- OceanBase 原始碼解讀(十二):宏塊的垃圾回收和壞塊檢查原始碼
- Oracle 控制檔案損壞解決方案Oracle
- 壞塊的處理思維(用程式製作壞塊不如用系統)
- 如何處理Oracle資料庫中的壞塊問題(轉)Oracle資料庫
- 恢復SDS中壞掉的一塊硬碟的資料(轉)硬碟
- ORA-01578(資料塊損壞)跳過壞塊處理辦法
- oracle壞塊修復例項Oracle
- Oracle 11.1 邏輯壞塊Oracle
- Oracle壞塊問題總結Oracle