Oracle備份/恢復案例07——回滾數據恢復
??? 回滾段表空間中的一個數據文件丟失或者損壞導致數據庫無法識別它,在啟動數據庫的時候會出現ORA-1157, ORA-1110的錯誤,或者操作系統級別的錯誤,例如ORA-7360。
??? 在關閉數據庫的時候(normal或者immediate)會出現ORA-1116, ORA-1110的錯誤,或者操作系統級別的錯誤,例如ORA-7368。
??? 感謝coolyl的辛勤工作,關于回滾段的大部分內容都是摘自他在itpub的文章。
1.損壞數據文件,但數據庫處于Open狀態
?
如果你發現有回滾段的數據文件丟失或者損壞了,而此時的數據庫是處于打開的狀態下并且在運行,就千萬不要關閉數據庫了,因為在大多數的情況下打開的時候比關閉的時候好解決問題一些。
一般也是存在有兩種情況:
A、offline丟失或損壞的數據文件,然后從一個備份中恢復,執行介質恢復以保持一致性。但是這種情況要求數據庫是歸檔方式下才可以采用的。
B、offline那個存在丟失或損壞的數據文件所在的整個回滾段表空間,然后刪除整個回滾段表空間并重建,但是你必須要殺掉那些在回滾段中已經激活的用戶進程才可以offline的。
通常第一種情況就比較簡單實現,但是更多的用戶事務將會出錯并且回滾。
A的具體步驟:
1、offline丟失或損壞的數據文件
SQL> ALTER DATABASE DATAFILE '<full_path_file_name>' OFFLINE;
2、從一個有效的備份中恢復
3、執行以下查詢
SELECT V1.GROUP#, MEMBER, SEQUENCE#
? FROM V$LOG V1, V$LOGFILE V2
?WHERE V1.GROUP# = V2.GROUP#;
這個將列出你的所有redolog文件以及它們所代表的sequence numbers
4、恢復數據文件
SQL> RECOVER DATAFILE '<full_path_file_name>';
5、確信你應用了所有的redolog文件,直至出現提示信息“Media recovery complete”
6、online那個數據文件
SQL> ALTER DATABASE DATAFILE '<full_path_file_name>' ONLINE;
?
B的具體步驟:
?
1、offline存在丟失或損壞的數據文件的回滾段表空間中的所有回滾段
?
SQL> ALTER ROLLBACK SEGMENT '<rollback_segment>' OFFLINE;
?
2、檢測當然回滾段的狀態
SELECT SEGMENT_NAME, STATUS FROM DBA_ROLLBACK_SEGS
?WHERE TABLESPACE_NAME = '<TABLESPACE_NAME>';
3、刪除所有offline的回滾段
SQL> DROP ROLLBACK SEGMENT <rollback_segment>;
4、處理那些online狀態的回滾段
重新執行第二步的查詢
SELECT SEGMENT_NAME, STATUS FROM DBA_ROLLBACK_SEGS
?WHERE TABLESPACE_NAME = '<TABLESPACE_NAME>';
如果你已經執行過offline操作的回滾段狀態仍然是online,則說明這個回滾段內有活動的事務。
?
你要接著查詢
SELECT SEGMENT_NAME, XACTS ACTIVE_TX, V.STATUS
? FROM V$ROLLSTAT V, DBA_ROLLBACK_SEGS
?WHERE TABLESPACE_NAME = '<TABLESPACE_NAME>' AND SEGMENT_ID = USN;
如果沒有返回結果,則證明存在丟失或損壞的數據文件的回滾段表空間中的所有回滾段都已經被offline了,然后重新執行第2步,第3步。
?
如果查詢有結果返回,則狀態應該是“PENDING OFFLINE”,接著查看ACTIVE_TX列,如果值為0,則表明此回滾段中已經沒有未處理的事務了,很快就會被offline的,然后等它offline后重新執行2,3步后跳至第6步;如果值大于0,則繼續到第五步。
5、強制那些包含活動事務的回滾段offline
活動的事務應該被提交或者回滾,執行下面的查詢看看哪些用戶占用了回滾段:
SELECT S.SID, S.SERIAL#, S.USERNAME, R.NAME "ROLLBACK"
? FROM V$SESSION S, V$TRANSACTION T, V$ROLLNAME R
?WHERE R.NAME IN ('<PENDING_ROLLBACK_1>', ... , '<PENDING_ROLLBACK_N>')
?? AND S.TADDR = T.ADDR AND T.XIDUSN = R.USN;
最好能直接聯系到那些user讓他們自己去回滾或者提交事務,如果不能做到的話,那就只能強制性的殺掉進程了。
ALTER SYSTEM KILL SESSION '<SID>, <SERIAL#>';
殺掉進程后再過一段時間后回滾段會自動清除那些事務,然后就可以回到第二步繼續查詢了。
6、刪除回滾段
SQL> DROP TABLESPACE <tablespace_name> INCLUDING CONTENTS;
7、重建回滾段并online它們
?
說明:
1、數據庫如果是open狀態,就可以直接在open狀態下解決問題,沒有必要停下數據庫,增加down機時間
2、不管上上面那種恢復方法都是正常性的恢復,不會引起數據的不一致或錯誤。
?
?
2.數據庫關閉,但是數據文件中沒有活動事務
這種情況下最簡單的方法就是offline drop掉這個壞了的或者丟失的數據文件,然后以restricted模式打開數據庫然后刪除并且重建包含損壞文件的回滾段表空間。
?
具體步驟如下:
?
1、確定數據庫是正常的關閉的。方法是可以去查看alert文件,到最后看是否有如下信息:
alter database dismount
Completed: alter database dismount
如果有的話,就證明數據庫是正常關閉的,否則就不能用這個方法去恢復。
?
2、修改init參數文件,移去ROLLBACK_SEGMENTS中包含的損壞數據文件的回滾段表空間的回滾段
?
如果你不能確定哪些回滾段是壞的,簡單的方法是你可以注釋掉整個ROLLBACK_SEGMENTS
3、以restricted模式去mount數據庫
SQL> STARTUP RESTRICT MOUNT;
4、offline drop掉那個壞的數據文件
SQL> ALTER DATABASE DATAFILE '<full_path_file_name>' OFFLINE DROP;
5、打開數據庫
SQL> ALTER DATABASE OPEN;
如果你看到如下信息“Statement processed”,則跳到第7步,如果你看到ORA-604, ORA-376, and ORA-1110的錯誤信息,繼續第6步。
6、正常的關閉數據庫,然后在init文件中注釋掉ROLLBACK_SEGMENTS,并加入隱含參數
_corrupted_rollback_segments = ( <rollback1>,...., <rollbackN> )
然后以restricted模式打開數據庫
SQL> STARTUP RESTRICT
7、刪除掉那個包含損壞文件的回滾段表空間
DROP TABLESPACE <tablespace_name> INCLUDING CONTENTS;
8、重建回滾段表空間,記得創建后要把回滾段都online
9、重新使數據庫對所有用戶可用
SQL> ALTER SYSTEM DISABLE RESTRICTED SESSION;
10、然后正常關閉數據庫,修改init文件
?
如果開始只是注釋掉了ROLLBACK_SEGMENTS的,就去掉注釋即可,如果加了隱含參數的,注釋掉它,并在ROLLBACK_SEGMENTS加入所有的回滾段。
?
11、正常啟動數據庫
SQL> Startup;
?
說明:
1、這種方法的前提條件是數據庫是正常關閉(不是abort)可用
2、這種方法是正常方法,不會引起數據錯誤
?
?
3.數據庫關閉,數據文件中有活動事務,沒有可用備份
一般造成這種原因的情況是采用了shutdown abort或其它原因異常關機(如斷電)導致的
1、開啟一個事務
?
SQL> set transaction use rollback segment rbs0;
Transaction set.
SQL> insert into test (a) values (1);
1 row created.
2、異常關閉
SQL> shutdown abort;
ORACLE instance shut down.
3、刪除rbs的一個數據文件
C:>del D:\oracle\oradata\dodo\UNDOTBS01.DBF
4、修改INIT<sid>.ora
rollback_segments=(system)
添加_corrupted_rollback_segments=(rbs0,rbs1,rbs2……)
5、SQL>Startup mount
6、Drop掉表空間
?
SQL>alter database datafile 'D:\oracle\oradata\dodo\UNDOTBS01.DBF' offline drop;
Database altered.
7、SQL>recover database;
8、SQL>alter database open;
Database altered.
9、SQL>select * from v$rollname;
?????? USN NAME
---------- ------------------------------
???????? 0 SYSTEM
10、SQL>select segment_name,tablespace_name,status from dba_rollback_segs;
SEGMENT_NAME?????????????????? TABLESPACE_NAME??????????????? STATUS
------------------------------ ------------------------------ ----------------
SYSTEM???????????????????????? SYSTEM???????????????????????? ONLINE
RBS0 ????????????????????????? RBS ?????????????????????????? NEEDS RECOVERY
RBS1 ????????????????????????? RBS ?????????????????????????? NEEDS RECOVERY
RBS2 ????????????????????????? RBS ?????????????????????????? NEEDS RECOVERY
11、Drop segment
?
SQL>drop rollback segment rbs0;
重算段已丟棄。
SQL>drop rollback segment rbs1;
重算段已丟棄。
SQL>drop rollback segment rbs2;
重算段已丟棄。
12、SQL>select segment_name,tablespace_name,status from dba_rollback_segs;
?
SEGMENT_NAME?????????????????? TABLESPACE_NAME??????????????? STATUS
------------------------------ ------------------------------ ----------------
SYSTEM???????????????????????? SYSTEM???????????????????????? ONLINE
13、SQL>drop tablespace rbs including contents;
表空間已丟棄。
14、重建新的回滾表空間及回滾段,并聯機。
15、SQL>shutdown abort
16、再修改INIT<sid>.ora
rollback_segments=(rbs0,rbs1,rbs2)
將_corrupted_rollback_segments=(rbs0,rbs1,rbs2)去掉
17、SQL>startup
?
?
說明:
1、這種辦法是萬不得以的時候使用的方法,如果有備份,都建議從備份上進行恢復
2、這種方法恢復的數據庫,可能會引起數據庫的數據錯誤
3、恢復成功以后,建議exp/imp數據,并重新分析檢查數據庫
?
4.數據庫關閉,數據文件中有活動事務,從備份恢復
1、從一個有效的備份中恢復損壞的數據文件
2、mount數據庫
3、執行以下查詢
SELECT FILE#, NAME, STATUS FROM V$DATAFILE;
如果發現要恢復的文件是offline狀態的話,要先online它:
ALTER DATABASE DATAFILE '<full_path_file_name>' ONLINE;
4、執行以下查詢
SELECT V1.GROUP#, MEMBER, SEQUENCE#, FIRST_CHANGE#
? FROM V$LOG V1, V$LOGFILE V2
?WHERE V1.GROUP# = V2.GROUP# ;
這個將列出redlog文件所代表的sequence和first change numbers
5、如果數據庫是非歸檔情況下,執行以下查詢:
SELECT FILE#, CHANGE# FROM V$RECOVER_FILE;
如果CHANGE#大于最小的redolog文件的FIRST_CHANGE#,則數據文件可以被恢復,記得在應用日志的時候要把所有redolog文件全部應用一遍。
如果CHANGE#小于最小的redolog文件的FIRST_CHANGE#,則數據文件就不可以被恢復了,這時候你要從一個有效的全備份中去恢復數據庫了,如果沒有全備份的話,那你就只能把數據庫強制打開到一個不一致的狀態去exp出數據,然后重新建庫導入數據,因為這種方式的恢復oracle是不推薦用戶自己做的,所以這里我就不詳細說明了。
?
6、恢復數據文件
RECOVER DATAFILE '<full_path_file_name>' ;
7、確信你應用了所有的redolog文件,直至出現提示信息“Media recovery complete”
8、打開數據庫
?
說明:
1、這種方法要求在歸檔有備份的方式下進行,而且是建議方式
2、這種方法不會導致數據庫的錯誤