Oracle 实例恢复与崩溃恢复

Oracle 实例恢复与崩溃恢复

适用版本:Oracle Database 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

实例恢复(Instance Recovery) 是数据库异常关闭后,启动时自动将数据库恢复到一致状态的过程[1]。

触发场景

  • SHUTDOWN ABORT
  • 实例崩溃(断电、OOM、进程被杀)
  • 节点故障后 RAC 重启动
  • 实例异常终止后 STARTUP

核心机制:利用 Redo Log 重做未落盘的修改,利用 Undo 回滚未提交事务。


2. 实例恢复的必要性

2.1 为什么需要恢复

Oracle 的写策略:

  • LGWR 先写 Redo Log(commit 时)
  • DBWn 异步写数据块(延迟写)

因此存在时间差:

T1: 事务 COMMIT → LGWR 写 Redo Log
T2: 实例崩溃(DBWn 还未写数据块)

T3: 重启实例
→ 数据文件中没有该事务的修改
→ Redo Log 中有该事务的记录
→ 需要 Redo 重做

2.2 一致性状态判断

-- 启动到 MOUNT 状态查询
STARTUP MOUNT;

-- 检查每个数据文件的 SCN
SELECT 
  f.file#,
  f.name,
  f.checkpoint_change# AS file_ckpt_scn,
  h.checkpoint_change# AS header_ckpt_scn,
  f.last_change# AS stop_scn
FROM v$datafile f
JOIN v$datafile_header h ON f.file# = h.file#;

-- 正常关闭:
-- stop_scn = file_ckpt_scn = header_ckpt_scn
-- 不需要恢复

-- 异常关闭:
-- stop_scn = NULL(或与 file_ckpt_scn 不等)
-- 需要实例恢复

3. 实例恢复的两个阶段

3.1 前滚(Roll Forward / Cache Recovery)

从 Redo Log 中重做检查点之后的所有变更,包括已提交和未提交的事务[1][2]:

Redo Log:
+---------+---------+---------+---------+---------+
| Redo 1  | Redo 2  | Redo 3  | Redo 4  | Redo 5  |
+---------+---------+---------+---------+---------+

                          Checkpoint RBA
[--------- 已落盘 ---------][------ 前滚范围 ------]

前滚过程:
1. 从 Checkpoint RBA 开始读 Redo
2. 对每条 Redo 记录:
   a. 找到对应数据块
   b. 比较数据块 SCN 与 Redo SCN
   c. 若 Redo SCN > 块 SCN,应用 Redo
   d. 否则跳过
3. 直到 Redo 末尾

3.2 打开数据库

前滚完成后,数据库达到一致状态,可以打开供用户访问。

3.3 回滚(Roll Back / Transaction Recovery)

打开数据库后,后台 SMON 异步回滚未提交事务[2]:

Undo 段中记录了未提交事务的旧值
回滚过程:
1. 扫描 Undo 段,找出未提交的事务
2. 对每个事务:
   a. 从 Undo 记录中取旧值
   b. 将数据块恢复到旧值
3. 标记事务为 ROLLED BACK

注意:回滚是异步进行的,用户可继续访问数据库,但访问未提交事务修改的数据时需要等待回滚完成。


4. 实例恢复详细流程

1. STARTUP NOMOUNT
   - 读取参数文件
   - 分配 SGA
   - 启动后台进程

2. STARTUP MOUNT
   - 读取控制文件
   - 检查数据文件状态
   - 发现 stop_scn = NULL,需要恢复

3. 前滚阶段
   - SMON 读取 Redo Log
   - 从 Checkpoint RBA 开始重做
   - 并行恢复(PARALLEL_RECOVERY)
   - 推进数据文件 SCN

4. 打开数据库
   - 数据文件 SCN 与控制文件一致
   - 打开数据文件
   - 用户可访问

5. 回滚阶段(SMON 异步)
   - 扫描 Undo 段
   - 回滚未提交事务
   - 释放事务锁

6. 完成
   - 数据库完全可用

警报日志示例

Sun Jul 21 10:23:15 2026
Starting ORACLE instance (normal)
...
ALTER DATABASE   MOUNT
Successful mount of redo thread 1
Database mounted in Exclusive Mode
Sun Jul 21 10:23:25 2026
ALTER DATABASE OPEN
Beginning crash recovery of 1 threads
 parallel recovery started with 4 processes
Started redo scan
Completed redo scan
 read 512 KB redo, 152 data blocks need recovery
Started redo application at
 Thread 1: logseq 245, block 1024
Recovery of Online Redo Log: Thread 1 Group 2 Seq 245 Reading mem 0
Completed redo application of 0.05MB
Crash recovery applied 152 redo records and 152 data blocks
Completed crash recovery at
Thread 1: logseq 245, block 1320, scn 1234567890
48 data blocks read, 48 data blocks written, 152 redo records read
Database opened.

5. RAC 中的实例恢复

RAC 中某节点崩溃后,幸存节点自动执行实例恢复[3]:

节点 1 崩溃 → 节点 2 检测到 → 节点 2 执行实例恢复

RAC 实例恢复特点

  • 由幸存节点的 SMON 执行
  • 需要读取崩溃节点的 Thread(Redo Log)
  • Cache Fusion 锁资源需要重整
  • 用户感知:极短暂停顿后继续可用

6. 实例恢复 vs 介质恢复

维度实例恢复介质恢复
触发异常重启数据文件损坏/丢失
数据来源在线 Redo Log归档 Redo Log + 在线 Redo Log
执行者SMON 自动DBA 手动(RMAN/SQL*Plus)
是否需要备份是(除非仅 Redo 丢失)
恢复时间秒-分钟分钟-小时

7. MTTR(Mean Time To Recover)

MTTR = 实例恢复时间,受 FAST_START_MTTR_TARGET 参数控制:

SHOW PARAMETER fast_start_mttr_target;

-- 设置目标 MTTR 为 60 秒
ALTER SYSTEM SET fast_start_mttr_target=60 SCOPE=BOTH;

MTTR 估算

SELECT 
  recovery_estimated_ios,
  actual_redo_blks,
  target_redo_blks,
  fast_start_mttr_target_redo_blks
FROM v$instance_recovery;

详细内容见:Oracle 检查点 Checkpoint 机制详解


8. 加速实例恢复

8.1 调整 MTTR 目标

-- OLTP 推荐 60-120 秒
ALTER SYSTEM SET fast_start_mttr_target=60 SCOPE=BOTH;

8.2 并行恢复

-- 启用并行恢复
ALTER SYSTEM SET recovery_parallelism=4 SCOPE=SPFILE;
-- 或使用并行度参数
ALTER SYSTEM SET parallel_recovery_stopat=600 SCOPE=SPFILE;

-- 重启生效
SHUTDOWN IMMEDIATE;
STARTUP;

8.3 增加 DBWn 进程

ALTER SYSTEM SET db_writer_processes=4 SCOPE=SPFILE;

8.4 优化 Redo Log

-- 合适的 Redo Log 大小,避免频繁切换
SELECT group#, bytes/1024/1024 AS mb, status FROM v$log;
-- 推荐:单组大小让日志切换间隔 15-30 分钟

9. 实例恢复监控

9.1 实时监控

-- 查看恢复进度(恢复过程中)
SELECT 
  sid,
  serial#,
  program,
  event,
  seconds_in_wait
FROM v$session
WHERE program LIKE '%RECO%' OR program LIKE '%SMON%';

9.2 历史恢复信息

-- 查看最近恢复信息
SELECT 
  startup_time,
  logins,
  status,
  archiver,
  parallel,
  thread#
FROM v$instance;

-- 警报日志检查
-- grep "crash recovery" alert_orcl.log

9.3 检查回滚进度

-- 查看待回滚事务
SELECT 
  local_tran_id,
  state,
  mixed
FROM dba_2pc_pending
WHERE state <> 'forced commit';

-- 查看回滚进度(10g+)
SELECT 
  usn,
  state,
  undoblocksdone,
  undoblockstotal
FROM v$fast_start_transactions;

-- 进度百分比
SELECT 
  ROUND(SUM(undoblocksdone)/NULLIF(SUM(undoblockstotal),0)*100, 2) AS pct
FROM v$fast_start_transactions;

10. 常见坑与排错

10.1 恢复过程中无法连接

现象:STARTUP 后无法登录,提示数据库未打开。

澄清:实例恢复期间数据库处于 MOUNT 状态,未 OPEN。

处理:等待恢复完成,监控警报日志。

10.2 ORA-01113: file needs media recovery

现象

ORA-01113: file 1 needs media recovery
ORA-01110: data file 1: '/u01/oradata/orcl/system01.dbf'

原因:实例恢复无法完成(如 Redo Log 损坏)。

修复

-- 启动到 MOUNT
STARTUP MOUNT;

-- 使用 RMAN 介质恢复
RMAN> RECOVER DATABASE;

-- 完成后打开
SQL> ALTER DATABASE OPEN;

10.3 ORA-01589: must use RESETLOGS

现象

ORA-01589: must use RESETLOGS or NORESETLOGS option for database open

原因:不完全恢复后需要 RESETLOGS。

修复

-- 如果是不完全恢复
ALTER DATABASE OPEN RESETLOGS;

-- 备份恢复后
ALTER DATABASE OPEN NORESETLOGS;

10.4 回滚耗时过长

现象:数据库 OPEN 后,应用响应慢,发现 SMON 在回滚大量事务。

排查

SELECT 
  pid, state, undoblocksdone, undoblockstotal,
  ROUND(undoblocksdone/NULLIF(undoblockstotal,0)*100, 2) AS pct
FROM v$fast_start_transactions;

加速

-- 增加并行回滚
ALTER SYSTEM SET fast_start_parallel_rollback=HIGH SCOPE=BOTH;
-- HIGH = 4×CPU_COUNT 并行度

10.5 RAC 节点恢复失败

现象:节点 1 崩溃后,节点 2 无法执行实例恢复。

原因:节点 1 的 Redo Thread 未被关闭。

修复

-- 在幸存节点执行
ALTER DATABASE DISABLE THREAD 1;
-- 后续根据需要重新启用

11. 最佳实践

  1. 设置合理的 FAST_START_MTTR_TARGET:60-120 秒
  2. 避免 SHUTDOWN ABORT:除非紧急情况
  3. ABORT 后立即备份:避免后续故障叠加
  4. 启用并行恢复recovery_parallelism 参数
  5. 合理规划 Redo Log:大小、组数、多路复用
  6. 监控 MTTR:定期检查 v$instance_recovery
  7. 关键业务启用 RAC:单节点故障自动切换
  8. 定期灾备演练:验证恢复流程

12. 参考资料

[1] Oracle Database Concepts 19c, “Instance Recovery” https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/instance-recovery.html

[2] Oracle Database Administrator’s Guide 19c, “Performing Instance Recovery” https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/instance-and-media-recovery.html

[3] Oracle Real Application Clusters Administration and Deployment Guide 19c https://docs.oracle.com/en/database/oracle/oracle-database/19/racad/

[4] Oracle Support Note 1424962.1, “Crash Recovery Internals” https://support.oracle.com/epmos/faces/DocumentDisplay?id=1424962.1