數據庫版本:9.2.0.5.0
平臺:windows2003
下午接到通知以數據庫出現壞塊現象,無備份,應用無法正常使用,要予以解決由於沒有備份,無法恢復,只能採用跳過壞塊方法,然後通過業務補數據。
首先要通知業務需要停服務,其次用PL/SQL登錄把OPTCABLE表的sql導出來。
首先要查出壞塊中的對象是什麼 file_id爲截圖中文件號,and 爲數據庫的塊號。
SQL> SELECT tablespace_name,segment_type, owner, segment_name FROM dba_extents WHERE file_id =82 AND 326677between block_id AND block_id + blocks - 1;
TABLESPACE_NAME SEGME OWNER SEGMENT_NAME
------------------------------ ---------- --------- --------
USERS TABLE GISTAR OPTCABLE
然後需要查詢數據對象的id(用於查詢rowid的參數)
SQL> SELECT data_object_id FROMdba_objects WHERE object_name = 'OPTCABLE' and owner='GISTAR';
DATA_OBJECT_ID
--------------
97248
找出壞塊最小的rowid (1, DATA_OBJECT_ID ,file_id,數據庫的塊號,0)
SQL> select dbms_rowid.rowid_create(1,97248,82,326677,0) from dual;
DBMS_ROWID.ROWID_C
------------------
AAAXvgABSAABPwVAAA
找出壞塊最大的rowid (1, DATA_OBJECT_ID ,file_id,數據庫的塊號+1,0)
SQL> select dbms_rowid.rowid_create(1,97248,82,326678,0) from dual;
DBMS_ROWID.ROWID_C
------------------
AAAXvgABSAABPwWAAA
然後通過rowid來確定壞塊數據的範圍,以便排除
這裏要注意,rowid的取值一定要大於大的,小於小的(上步驟查詢出來的2個rowid)
SQL> SELECT /*+ ROWID(A) */ COUNT(*)FROM OPTCABLE A WHERE ROWID>='AAAXvgABSAABPwWAAA';
當進行查詢時又報出undo表空間也有壞塊
ERROR 位於第 1 行:
ORA-01578: ORACLE 數據塊損壞(文件號107,塊號225)
ORA-01110: 數據文件 107:'D:\ORACLE\ORADATA\LNXC\UNDOTBS07.DBF'
解決此問題要替換undo表空間(注意未結束的回滾段)
create undo tablespace undo2 datafile'd:\oracle\oradata\lnxc\undo02_01.dbf' size 2048M;
alter system set undo_tablespace=undo2;
重啓數據庫後查詢undo信息(undo已經更換)
SQL> show parameter undo;
NAME TYPE VALUE
-------------------------------------------- ------------------------------
undo_management string AUTO
undo_retention integer 10800
undo_suppress_errors boolean FALSE
undo_tablespace string UNDO2
刪除老undo表空間報錯,發現了未結束的回滾段
SQL> drop tablespace UNDOTBS1 includingcontents and datafiles;
drop tablespace UNDOTBS1 including contentsand datafiles
*
ERROR 位於第 1 行:
ORA-01548: 已找到活動回退段'_SYSSMU5$',終止刪除表空間
創建pfile
SQL> create pfile='d:\t.txt' fromspfile;
關閉實例
SQL> shutdown immediate
編輯pfile加入如下參數(注意,CORRUPTED_ROLLBACK_SEGMENTS中一定要包含未結束的回滾段)
*.undo_management='MANUAL'
*._CORRUPTED_ROLLBACK_SEGMENTS=(_SYSSMU5$,_SYSSMU6$,_SYSSMU7$,_SYSSMU8$,_SYSSMU9$,_SYSSMU10$)
用pfile啓動數據庫
SQL> startup pfile='d:\t.txt';
刪除原來的undo表空間(數據文件也刪除)
SQL> drop tablespace UNDOTBS1 includingcontents and datafiles;
再用spfile重啓數據庫,因爲我們要用undo2表空間進行修復(不用指定參數文件,默認)
startup
查詢undo段信息
SQL> selectsegment_name,status,tablespace_name from dba_rollback_segs;
SEGMENT_NAME STATUS TABLESPACE_NAME
-------------------- ----------------------------------------------
SYSTEM ONLINE SYSTEM
_SYSSMU17$ ONLINE UNDO2
_SYSSMU18$ ONLINE UNDO2
_SYSSMU19$ ONLINE UNDO2
_SYSSMU20$ ONLINE UNDO2
_SYSSMU21$ ONLINE UNDO2
_SYSSMU22$ ONLINE UNDO2
_SYSSMU23$ ONLINE UNDO2
_SYSSMU24$ ONLINE UNDO2
_SYSSMU25$ ONLINE UNDO2
_SYSSMU26$ ONLINE UNDO2
發現沒有問題,切換生產用戶,繼續修復壞塊
然後通過rowid來確定壞塊數據的範圍,以便排除
這裏要注意,rowid的取值一定要大於大的,小於小的(上步驟查詢出來的2個rowid)
SQL> SELECT /*+ ROWID(A) */ COUNT(*)FROM OPTCABLE A WHERE ROWID>='AAAXvgABSAABPwWAAA';
COUNT(*)
----------
151362
SQL> SELECT /*+ ROWID(A) */ COUNT(*)FROM OPTCABLE A WHERE ROWID<'AAAXvgABSAABPwVAAA';
COUNT(*)
----------
27699
以原表結構創建一個新表,用來存放該表完好的數據(rowid依然大於大的小於小的)
SQL> CREATE TABLE OPTCABLE_BAK AS SELECT/*+ ROWID(A) */ * FROM OPTCABLE A WHERE ROWID>='AAAXvgABSAABPwWAAA';
SQL> INSERT INTO OPTCABLE_BAK SELECT /*+ ROWID(A) */ * FROMOPTCABLE A WHERE ROWID<'AAAXvgABSAABPwVAAA';
SQL> commit;
現在就把完好的數據成功找回,這裏注意不要用rename的方式去修改表名讓業務使用,因爲新創建表字段的默認值已經丟失,還需要重新加默認值。
按照一開始用PL/SQL導出的表sql去重新創建表結構,非表對象等等。
然後重新插入數據
SQL> insert into optcable select * fromoptcable_bak;
SQL> commit;
刪除創建的臨時表(9i或9i以上沒有開回收站的數據庫不用加purge,其他建議加purge)
SQL> drop table optcable_bak;
SQL> drop table optcable_bak1;
到此壞塊問題解決,如果11G版本還有統計信息的,建議追加統計信息。
原文鏈接:https://blog.csdn.net/roc_phoneix/article/details/39637235