第13章 无备份情况下的恢复
恢复密码文件
密码文件默认路径:$ORACLE_HOME/dbs/orapw实例名
密码文件只为sysydba、sysoper、sysasm角色服务
su - oracle
orapwd file=$ORACLE_HOME/dbs/orapwTESTDB password=oracle force=y
恢复参数文件
必须的参数只有两个:DB_NAME、CONTROL_FILES
INSTANCE_NAME和SERVICE_NAMES可以从环境变量ORACLE_SID、密码文件名及tnsnames中找回
如果使用了不同大小数据块的表空间,切记设置DN_nK_CACHE_SIZE参数
audit_file_dest='/u01/app/oracle/admin/TESTDB/adump/'
audit_trail='DB'
background_dump_dest='/u01/app/oracle/diag/rdbms/icu/TESTDB/trace' #Deprecate parameter
compatible='11.2.0.4.0'
control_files='/oradata/TESTDB/control01.ctl'
control_files='/u01/app/oracle/fast_recovery_area/TESTDB/control02.ctl' # Restore Controlfile
core_dump_dest='/u01/app/oracle/diag/rdbms/icu/TESTDB/cdump'
db_block_size=8192
db_domain=''
db_name='ICU'
diagnostic_dest='/u01/app/oracle'
dispatchers='(PROTOCOL=TCP) (SERVICE=ICUXDB)'
log_archive_dest_1='location=/arch'
log_buffer=6488064 # log buffer update
memory_target=1648M
open_cursors=300
optimizer_dynamic_sampling=2
optimizer_mode='ALL_ROWS'
plsql_warnings='DISABLE:ALL' # PL/SQL warnings at init.ora
processes=150
query_rewrite_enabled='TRUE'
remote_login_passwordfile='EXCLUSIVE'
result_cache_max_size=4224K
skip_unusable_indexes=TRUE
undo_tablespace='UNDOTBS1'
user_dump_dest='/u01/app/oracle/diag/rdbms/icu/TESTDB/trace' #Deprecate parameter
恢复控制文件
在线日志无损情况下的重建
# 启动数据库到nomount
startup nomount;
# 重建控制文件,注意使用noresetlogs关键字
create controlfile reuse database TESTDB noresetlogs archivelog
maxlogfiles 50
maxlogmembers 3
maxdatafiles 200
maxinstances 6
maxloghistory 200
logfile
group 1 ('/data/TESTDB/redo01A.log',
'/data/TESTDB/redo01B.log',
) SIZE 200M BLOCKSIZE 512,
group 2 ('/data/TESTDB/redo02A.log',
'/data/TESTDB/redo02B.log',
) SIZE 200M BLOCKSIZE 512,
group 3 ('/data/TESTDB/redo03A.log',
'/data/TESTDB/redo03B.log',
) SIZE 200M BLOCKSIZE 512
datafile
'/data/TESTDB/system01.dbf',
'/data/TESTDB/sysaux01.dbf',
'/data/TESTDB/undotbs01.dbf',
'/data/TESTDB/users01.dbf'
CHARACTER SET AL32UTF8; #注意字符集AL32UTF8/ZHS16GBK
# 重建完控制文件后数据库会自动进入mount状态,在SQLPLUS下手工发起介质恢复操作
SQLplus / as sysdba
recover database;
# 打开数据库
alter database open;
# 将临时文件添加回所在的临时表空间
alter tablespace temp add tempfile '/data/TESTDB/temp01.dbf' reuse;
# 从快速恢复区找回rman备份信息(没有使用catalog数据库的情况下)
rman target /
catalog db_recovery_file_dest;
在线日志损坏情况下的重建
# 启动数据库到nomount
startup nomount;
# 重建控制文件,注意使用resetlogs关键字
create controlfile reuse database TESTDB resetlogs archivelog
maxlogfiles 50
maxlogmembers 3
maxdatafiles 200
maxinstances 6
maxloghistory 200
logfile
group 1 ('/data/TESTDB/redo01A.log',
'/data/TESTDB/redo01B.log',
) SIZE 200M BLOCKSIZE 512,
group 2 ('/data/TESTDB/redo02A.log',
'/data/TESTDB/redo02B.log',
) SIZE 200M BLOCKSIZE 512,
group 3 ('/data/TESTDB/redo03A.log',
'/data/TESTDB/redo03B.log',
) SIZE 200M BLOCKSIZE 512
datafile
'/data/TESTDB/system01.dbf',
'/data/TESTDB/sysaux01.dbf',
'/data/TESTDB/undotbs01.dbf',
'/data/TESTDB/users01.dbf'
CHARACTER SET AL32UTF8; #注意字符集AL32UTF8/ZHS16GBK
# 从快速恢复区找回rman备份信息(没有使用catalog数据库的情况下)
rman target /
catalog db_recovery_file_dest;
# 尝试完全恢复,看它能走多远(在线日志损坏必然是不完全恢复)
run {
restore database;
recover database;
}
# 看报错日志。进行不完全恢复
recover database until sequence xx;
# resetlogs打开数据库
alter database open resetlogs;
# 找回临时文件
alter tablespace temp add tempfile '/data/TESTDB/temp01.dbf' reuse;
具有只读数据文件情况下的重建
- 注意数据文件中不能包含只读数据文件
原因:228页 控制文件会将只读数据文件当成可读写的数据文件处理,只读数据文件头部的SCN可能非常旧,旧到所有归档日志都无法将其恢复到当前的SCN
# 启动数据库到nomount
startup nomount;
# 重建控制文件,注意数据文件中不能包含只读数据文件
create controlfile reuse database TESTDB noresetlogs archivelog
maxlogfiles 50
maxlogmembers 3
maxdatafiles 200
maxinstances 6
maxloghistory 200
logfile
group 1 ('/data/TESTDB/redo01A.log',
'/data/TESTDB/redo01B.log',
) SIZE 200M BLOCKSIZE 512,
group 2 ('/data/TESTDB/redo02A.log',
'/data/TESTDB/redo02B.log',
) SIZE 200M BLOCKSIZE 512,
group 3 ('/data/TESTDB/redo03A.log',
'/data/TESTDB/redo03B.log',
) SIZE 200M BLOCKSIZE 512
datafile #不能包含只读数据文件
'/data/TESTDB/system01.dbf',
'/data/TESTDB/sysaux01.dbf',
'/data/TESTDB/undotbs01.dbf',
'/data/TESTDB/users01.dbf'
CHARACTER SET AL32UTF8; #注意字符集AL32UTF8/ZHS16GBK
# 从快速恢复区找回rman备份信息(没有使用catalog数据库的情况下)
rman target /
catalog db_recovery_file_dest;
# rman下完全恢复(观察报错情况)
recover database;
# 检查在线日志信息,看哪个是报错指示的在线日志文件,通常是current状态的那个
select lg.status,lg.group#,lg.sequence#,lm.member
from v$log lg,v$logfile lm
where lg.group#=lm.group#
order by 2;
# 在sqlplus中进行交互式recover恢复(还原或重建控制文件时,在sqlplus中必须使用using backup controlfile)
sqlplus / as sysdba
recover database using backup controlfile;
手工输入在线重做日志路径完成完全恢复
# 检查数据文件信息,发现没有只读数据文件信息
select file#,name from v$datafile;
# resetlogs方式打开数据库,只读数据文件信息会自动添加回控制文件
alter database open resetlogs;
# 再次检查数据文件信息,发现只读数据文件又回来了,但路径不正确
select file#,name from v$datafile;
# 修正路径问题
alter database rename file '错误的路径' to '正确的路径';
# 将只读表空间上线
alter tablespace 表空间名 online;
# 找回临时文件
alter tablespace temp add tempfile '/data/TESTDB/temp01.dbf' reuse;
使用控制文件快照恢复
控制文件快照相当于控制文件的镜像复制,默认路径是$ORACLE_HOME/dbs/snapcf_TESTDB.f
只要曾经备份过控制文件或与catalog同步过,快照就存在,可以使用操作系统命令将快照复制到控制文件路径,后续操作参照第8章控制文件的备份与恢复。
# 使用控制文件快照生成trace
alter database backup controlfile to trace;
#查看转储文件路径
select value from v$diag_info where name='Default Trace File';
恢复数据文件
普通数据文件在没有备份的情况下可以在控制文件和数据字典的帮助下通过重做日志恢复
除非数据文件创建不久没来得及备份就损坏,否则这种方式太过依赖归档日志,没有利用价值。
# 将损坏的普通数据文件下线
alter database datafile 6 offline;
# 打开数据库
alter database open;
# 创建新的空白数据文件
alter database create datafile 6;
# rman下恢复数据文件(归档日志必须齐全)
rman target /
recover datafile 6;
恢复临时文件
临时文件损坏只会导致使用临时表空间的命令失败,比如排序,并不会造成实例崩溃会会话中断。
RMAN并不备份临时文件,恢复策略是替换或重建。
# 新增一个临时文件
alter tablespace temp add tempfile '/data/TESTDB/temp02.dbf' size 40m autoextend on;
# 删除损坏的临时文件
alter tablespace temp drop tempfile '/data/TESTDB/temp01.dbf';
# 确认临时文件工作正常
select * from tb01 order by 1;
恢复在线重做日志
本节恢复策略的前提:数据库实例没有关闭
- 场景1:每个日志组有多个在线日志,某组中其中一个日志文件损坏
# 检查在线日志信息
select lg.status,lg.group#,lg.sequence#,lm.member
from v$log lg,v$logfile lm
where lg.group#=lm.group#
order by 2;
# 切归档,做checkpoint将损坏组状态置为inactive
alter system switch logfile;
alter system checkpoint;
# 再次检查在线日志信息,确认状态为inactive
select lg.status,lg.group#,lg.sequence#,lm.member
from v$log lg,v$logfile lm
where lg.group#=lm.group#
order by 2;
# 删除损坏的日志文件信息
alter database drop logfile member 'xxx';
# 创建一个新的(假设是1号组)
alter database add logfile member 'xxx' to group 1;
- 场景2:组内所有日志文件(非current状态)损坏
并不直接导致SQL命令无法执行,但是因为无法完成归档导致LGWR不能覆盖日志,日志缓冲区最终可能被充满,所有导致数据库变更的命令如dml,ddl都无法执行。
# 检查等待事件信息
select event,seconds_in_wait from v$session where wait_class <> 'Idle' order by 2 desc;
# 检查在线日志信息
select lg.status,lg.group#,lg.sequence#,lm.member
from v$log lg,v$logfile lm
where lg.group#=lm.group#
order by 2;
# 确认日志组状态为inactive后创建并格式化日志
alter database clear unarchived logfile group 1;
# 检查归档日志信息(发现某个归档日志消失了)
select sequence#,name from v$archived_log;
# 立即备份数据库,使用原来的备份只能恢复到丢失归档日志的前一个
backup database;
切记不要盲目重启实例,否则会导致不必要的不完全恢复。
直接从备份片中提取文件
以下代码在nomount状态下就能执行,而使用rman还原必须将数据库启动至mount状态。
# 利用RMAN功能包 dbms_back_restore 242页
sqlplus / as sysdba
startup nomount;
DECLARE
device varchar2(100);
done_out boolean;
outhandle_out varchar2(100);
outtag_out varchar2(100);
failover_out boolean;
BEGIN
sys.dbms_backup_restore.restoresetdatafile; --启动rman还原会话
sys.dbms_backup_restore.restoredatafileto( --指定被还原数据文件编号与路径
dfnumber => 5,
toname => '/backup/EXAMPLE02.DBF');
device := sys.dbms_backup_restore.deviceallocate;
sys.dbms_backup_restore.restoresetpiece( --指定还原使用的备份片
handle => '/backup/0e2t6a93_1_1',
tag => 'TAG20240612T152211',
fromdisk => true,
recid => 0,
stamp => 0);
sys.dbms_backup_restore.restorebackuppiece( --执行还原操作
done => done_out,
params => null,
outhandle => outhandle_out,
outtag => outtag_out,
failover => failover_out);
end;
/