Oracle 检查点(Checkpoint)机制详解

Oracle 检查点(Checkpoint)机制详解

适用版本:Oracle Database 11g / 12c / 19c / 23ai 阅读基础:了解 Buffer Cache、Redo Log、LGWR/DBWn/CKPT 进程的工作机制 文档版本:v1.0 / 2026-07


目录


1. 概述:检查点的作用与本质

检查点(Checkpoint)是 Oracle 数据库中保证数据一致性缩短实例恢复时间的核心机制[1][2]。

核心定义:检查点是数据库将**内存中已修改的数据(脏块)**写入数据文件,并同步控制文件和数据文件头部的 SCN 的过程。

作用

  1. 缩短实例恢复时间:检查点之前的修改已落盘,崩溃恢复时只需重做检查点之后的 Redo
  2. 保证数据一致性:将数据文件头部 SCN 与控制文件同步
  3. 释放 Redo Log 空间:检查点推进后,旧的 Redo Log 才能被覆盖
  4. 触发条件:日志切换、关闭数据库、FAST_START_MTTR_TARGET 触发等

核心流程

应用层                      内存层                     磁盘层
+----------+              +------------+           +------------+
|  DML     | ──修改──>   | Buffer     | ──脏块──> | Data File  |
|          |              | Cache      |   (DBWn)  |            |
|          |              |            |           +------------+
|          | ──记录──>   | Redo Log   | ──落盘──> | Redo Log   |
|          |              | Buffer     |   (LGWR)  | File       |
+----------+              +------------+           +------------+
                                |                       |
                                |    Checkpoint         |
                                +─── 同步 SCN ─────────+
                                                       |
                                              +----------------+
                                              | Control File   |
                                              | (CKPT 更新)    |
                                              +----------------+

2. 检查点的核心概念

2.1 SCN(System Change Number)

SCN 是 Oracle 数据库内部的逻辑时钟,标志着数据库的某个一致状态[2]:

-- 查询当前 SCN
SELECT current_scn FROM v$database;

-- 查询数据文件头 SCN
SELECT name, checkpoint_change#, status 
FROM v$datafile_header;

-- 查询控制文件中数据文件 SCN
SELECT name, checkpoint_change#, status 
FROM v$datafile;

关键 SCN 类型

SCN 类型含义
System Commit SCN最新 commit 的 SCN
Checkpoint SCN检查点推进到的 SCN
Datafile Checkpoint SCN数据文件头的 SCN
Stop SCN控制文件中数据文件的”停止 SCN”(数据库正常关闭时与 Checkpoint SCN 一致)
Thread Checkpoint SCNRedo Thread 的检查点 SCN

2.2 RBA(Redo Block Address)

RBA 是 Redo Log 中每一条记录的物理位置,由三部分组成:

RBA = (Log Sequence#, Block Number within log, Byte Offset within block)
    = (日志序列号,     块号,                  字节偏移)

例如:RBA = (0x245, 0x400, 0x10) 表示序列号 0x245 的日志中第 0x400 块的第 0x10 字节。

2.3 Checkpoint RBA

Checkpoint RBA 是检查点推进到的 RBA 位置:

  • 该 RBA 之前的所有 Redo 记录对应的脏块都已被 DBWn 写入数据文件
  • 实例恢复只需从 Checkpoint RBA 开始重做 Redo
  • Checkpoint RBA 越接近当前 Redo 位置,实例恢复越快

2.4 On-Disk RBA

On-Disk RBA 是 Redo Log 中已被 LGWR 写入磁盘的最新位置:

  • 比 Checkpoint RBA 更靠前
  • 是实例恢复的”上限”
Redo Log 时间轴:

0x000 ──────────────────────────────────────> 0xFFF
       │                        │              │
       │                        │              │
       ▼                        ▼              ▼
  Checkpoint RBA           On-Disk RBA    Current RBA
       │                        │              │
       │                        │              │
       └── 实例恢复需要重做的范围 ─┘              │

                                       LGWR 还未写入

3. 检查点的类型

3.1 完全检查点(Full Checkpoint)

触发条件

  • SHUTDOWN NORMAL/TRANSACTIONAL/IMMEDIATE
  • 手工执行:ALTER SYSTEM CHECKPOINT;
  • 日志切换(部分场景)

行为

  • 将 Buffer Cache 中所有脏块写入数据文件
  • 更新所有数据文件头 SCN
  • 更新控制文件中的检查点信息

特点

  • 一次写完所有脏块,可能产生大量 I/O
  • 完成后实例恢复时间最短
  • 通常不会频繁触发
-- 手动触发完全检查点
ALTER SYSTEM CHECKPOINT;

-- 全局检查点(RAC 所有节点)
ALTER SYSTEM CHECKPOINT GLOBAL;

3.2 增量检查点(Incremental Checkpoint)

触发条件

  • 每 3 秒 CKPT 自动触发
  • FAST_START_MTTR_TARGET 设置后持续触发
  • Redo Log 切换时
  • 检查点队列过长时

行为

  • 只更新控制文件中的 Checkpoint RBA
  • 不更新数据文件头 SCN
  • 不强制 DBWn 立即写入所有脏块
  • DBWn 在后台按 Checkpoint Queue 顺序写入脏块

特点

  • 频繁但开销小
  • 是 Oracle 8i 之后主要的检查点机制
  • 主要为了控制实例恢复时间

3.3 局部检查点(Partial Checkpoint)

触发条件

  • 将表空间设为 OFFLINE:ALTER TABLESPACE users OFFLINE
  • 将数据文件设为 OFFLINE:ALTER DATABASE DATAFILE ... OFFLINE
  • 删除表空间:DROP TABLESPACE users
  • BEGIN BACKUP 模式:ALTER TABLESPACE users BEGIN BACKUP
  • 执行 TRUNCATE:TRUNCATE TABLE tab

行为

  • 只将特定表空间或对象的脏块写入数据文件
  • 不影响其他表空间

3.4 对象检查点(Object Checkpoint)

触发条件

  • DROP TABLE / TRUNCATE TABLE
  • 表的 SHRINK SPACE
  • 索引重建

行为

  • 仅针对特定对象的脏块
  • 释放该对象占用的空间

4. 检查点队列(Checkpoint Queue)

Checkpoint Queue 是 Buffer Cache 中脏块按 RBA 排序的链表[3]:

脏块链表(按 RBA 升序):

+--------+    +--------+    +--------+    +--------+
| RBA=100| -> | RBA=200| -> | RBA=350| -> | RBA=500|
+--------+    +--------+    +--------+    +--------+


DBWn 从这里开始写入(最早变脏的脏块)

当 Checkpoint RBA 推进到 200 时:
+--------+    +--------+    +--------+
| RBA=350| -> | RBA=500|
+--------+    +--------+


            新加入的脏块(RBA 大于 500)

关键特性

  1. FIFO 顺序:先变脏的块先被写出
  2. RBA 顺序:保证 Checkpoint RBA 可以稳定推进
  3. DBWn 写入目标:DBWn 优先写队列头部脏块
  4. LRU 队列独立:Checkpoint Queue 与 LRU 队列分开维护

查看 Checkpoint Queue

-- 查看脏块数量
SELECT name, value 
FROM v$sysstat 
WHERE name IN ('DBWR checkpoint buffers written', 
               'DBWR checkpoints',
               'physical writes');

-- 查看检查点进度
SELECT 
  ctid, 
  rdtyp, 
  rdbno, 
  boff, 
  drba,    -- Checkpoint RBA
  iorba    -- On-Disk RBA
FROM x$kccrt;  -- 内部视图(需 SYSDBA)

5. CKPT 进程的职责

CKPT(Checkpoint Process)后台进程主要负责:

  1. 更新控制文件:在检查点触发时更新控制文件中的检查点信息
  2. 更新数据文件头:完全检查点时更新数据文件头 SCN
  3. 通知 DBWn:触发 DBWn 写入脏块(实际写盘由 DBWn 完成)
  4. 每 3 秒唤醒:维持心跳,推进增量检查点

注意

  • CKPT 本身不写数据块到数据文件
  • 写脏块的工作由 DBWn 完成
  • CKPT 只是”信使”,记录检查点位置

警报日志中可见

Sun Jul 21 10:23:15 2026
Beginning global checkpoint up to RBA [0x245.0x400.0x10], SCN: 1234567890
Completed checkpoint up to RBA [0x245.0x400.0x10], SCN: 1234567890

6. DBWn 与检查点的关系

DBWn(Database Writer)负责将脏块写入数据文件,与检查点紧密配合[3]:

6.1 DBWn 触发写脏块的场景

  1. 检查点触发:CKPT 通知 DBWn 写脏块
  2. LRU 链表扫描:扫描 LRU 寻找空闲块时,遇到脏块需要写出
  3. 空闲空间不足:Buffer Cache 空闲块少时
  4. 每 3 秒:DBWn 定时唤醒
  5. Ping 写:RAC 跨节点访问
  6. 表空间 OFFLINE/READ ONLY:写出该表空间脏块
  7. 关闭数据库(非 ABORT)

6.2 DBWn 写入策略

Checkpoint Queue(按 RBA 顺序)

       头部                          尾部
        ▼                            ▼
+-------+--------+--------+--------+--------+
|RBA=100|RBA=200 |RBA=350 |RBA=500 |RBA=800 |
+-------+--------+--------+--------+--------+


DBWn 从头部开始写:
1. 找到队列头部脏块
2. 多块写(batch write)到数据文件
3. 从 Checkpoint Queue 移除
4. 移到 LRU 的 MRU 端(变为干净块)
5. 继续写下一个,直到满足 Checkpoint RBA 推进

6.3 DBWn 进程数量

SHOW PARAMETER db_writer_processes;
-- 默认为 1,最大可设为 CPU_COUNT / 8

何时增加 DBWn 进程数

  • 写等待事件显著:free buffer waitswrite complete waits
  • 多 CPU 服务器,写密集型负载
-- 增加 DBWn 进程
ALTER SYSTEM SET db_writer_processes=4 SCOPE=SPFILE;
-- 重启生效
SHUTDOWN IMMEDIATE;
STARTUP;

7. 检查点相关参数

7.1 FAST_START_MTTR_TARGET

作用:设置实例恢复目标时间(秒),Oracle 自动调整检查点频率以达成目标[1]:

SHOW PARAMETER fast_start_mttr_target;
-- 默认 0(关闭),范围 0-3600 秒

-- 设置目标恢复时间为 60 秒
ALTER SYSTEM SET fast_start_mttr_target=60 SCOPE=BOTH;

工作原理

  • Oracle 持续估算当前累积的 Redo 量
  • 当估计恢复时间接近目标值时,触发 DBWn 写脏块
  • 推进 Checkpoint RBA,降低待恢复 Redo

权衡

设置实例恢复时间检查点开销
较小(如 30s)高(频繁 DBWn 写)
较大(如 600s)低(DBWn 写入少)
0(关闭)不保证由其他参数控制

推荐

  • OLTP:60-120 秒
  • 数据仓库:300-600 秒
  • 关键业务:30-60 秒

7.2 LOG_CHECKPOINT_INTERVAL

作用:每写 N 个 Redo Block 触发一次检查点(已被 FAST_START_MTTR_TARGET 取代)

SHOW PARAMETER log_checkpoint_interval;
-- 默认 0(关闭)

7.3 LOG_CHECKPOINT_TIMEOUT

作用:每 N 秒触发一次检查点(已被 FAST_START_MTTR_TARGET 取代)

SHOW PARAMETER log_checkpoint_timeout;
-- 默认 0(关闭),单位秒

7.4 LOG_CHECKPOINTS_TO_ALERT

作用:将每次检查点信息写入警报日志,便于排错

SHOW PARAMETER log_checkpoints_to_alert;
-- 默认 FALSE

ALTER SYSTEM SET log_checkpoints_to_alert=TRUE SCOPE=BOTH;

7.5 参数优先级

Oracle 推荐使用 FAST_START_MTTR_TARGET,其他参数置为 0:

ALTER SYSTEM SET fast_start_mttr_target=60 SCOPE=BOTH;
ALTER SYSTEM SET log_checkpoint_interval=0 SCOPE=BOTH;
ALTER SYSTEM SET log_checkpoint_timeout=0 SCOPE=BOTH;

8. 实例恢复与 MTTR

8.1 MTTR 估算

MTTR(Mean Time To Recover) = 崩溃后重启数据库的时间,主要由实例恢复构成:

MTTR = Redo 重放时间 + Undo 回滚时间

Redo 重放时间 ∝ 待恢复的 Redo 量
              ∝ (On-Disk RBA - Checkpoint RBA)

Undo 回滚时间 ∝ 未提交事务的数量

8.2 MTTR 估算视图

-- 查看 MTTR 估算
SELECT 
  mttr_target_for_estimate,  -- 推荐的 MTTR 目标
  estd_cache_size,           -- 对应的 cache 大小
  estd_cache_hit_ratio,      -- 缓存命中率
  estd_total_writes          -- 估计的写次数
FROM v$mttr_target_advice;

8.3 实例恢复过程

1. 实例崩溃(断电、SHUTDOWN ABORT)

2. STARTUP 启动:
   ┌─────────────────────────────────┐
   │ NOMOUNT                         │
   │ - 读参数文件,分配 SGA          │
   └─────────────────────────────────┘


   ┌─────────────────────────────────┐
   │ MOUNT                           │
   │ - 读控制文件                    │
   └─────────────────────────────────┘


   ┌─────────────────────────────────┐
   │ OPEN                            │
   │ - 实例恢复:                    │
   │   a. 前滚:从 Checkpoint RBA    │
   │      重做 Redo                  │
   │   b. 打开数据库(用户可访问)   │
   │   c. 后台异步回滚未提交事务     │
   └─────────────────────────────────┘

8.4 加速实例恢复

方法 1:设置合理的 FAST_START_MTTR_TARGET

ALTER SYSTEM SET fast_start_mttr_target=60 SCOPE=BOTH;

方法 2:增加 DBWn 进程

ALTER SYSTEM SET db_writer_processes=4 SCOPE=SPFILE;

方法 3:使用并行恢复

-- 设置恢复并行度
ALTER SYSTEM SET recovery_parallelism=4 SCOPE=SPFILE;
-- 或
ALTER SYSTEM SET parallel_recovery_stopat=600 SCOPE=SPFILE;

9. 检查点相关视图

9.1 V$DATABASE

SELECT 
  name, 
  log_mode, 
  checkpoint_change#,    -- 当前检查点 SCN
  current_scn            -- 当前系统 SCN
FROM v$database;

9.2 V$THREAD

SELECT 
  thread#, 
  status,
  sequence#,
  checkpoint_change#,
  checkpoint_time
FROM v$thread;

9.3 V$DATAFILE

SELECT 
  file#, 
  name, 
  status,
  checkpoint_change#,    -- 数据文件检查点 SCN
  last_change#,          -- 最后一次修改的 SCN
  offline_change#
FROM v$datafile;

9.4 V$INSTANCE_RECOVERY

-- 查看实例恢复动态信息
SELECT 
  recovery_estimated_ios,       -- 估计的恢复 I/O 数
  actual_redo_blks,             -- 当前需要恢复的 Redo 块数
  target_redo_blks,             -- 目标 Redo 块数
  log_file_size_redo_blks,      -- 受 Redo Log 大小限制
  log_chkpt_timeout_redo_blks,  -- 受超时限制
  fast_start_io_target_redo_blks,
  fast_start_mttr_target_redo_blks
FROM v$instance_recovery;

9.5 V$SYSSTAT

-- 查看检查点相关统计
SELECT name, value 
FROM v$sysstat 
WHERE name IN (
  'DBWR checkpoints',
  'DBWR checkpoint buffers written',
  'background checkpoints',
  'background checkpoints started',
  'background checkpoints completed'
);

9.6 V$SYSTEM_EVENT

-- 查看检查点相关等待事件
SELECT event, total_waits, time_waited
FROM v$system_event
WHERE event LIKE '%checkpoint%'
   OR event LIKE '%file sync%'
ORDER BY time_waited DESC;

10. 常见坑与排错

10.1 checkpoint not complete

现象:警报日志出现:

Sun Jul 21 10:23:15 2026
Thread 1 cannot allocate new log, sequence 246
Checkpoint not complete

原因

  • Redo Log 文件太小,切换过快
  • DBWn 写脏块速度跟不上 Redo 生成速度
  • 检查点未完成时 LGWR 需要覆盖未落盘的 Redo

修复

-- 1. 增加 Redo Log 文件大小
ALTER DATABASE ADD LOGFILE GROUP 4 
  ('/u01/oradata/orcl/redo04.log') SIZE 500M;
ALTER DATABASE ADD LOGFILE GROUP 5 
  ('/u01/oradata/orcl/redo05.log') SIZE 500M;

-- 2. 增加日志组数量(至少 3 组,推荐 4-6 组)

-- 3. 调整 FAST_START_MTTR_TARGET
ALTER SYSTEM SET fast_start_mttr_target=300 SCOPE=BOTH;

-- 4. 增加 DBWn 进程
ALTER SYSTEM SET db_writer_processes=4 SCOPE=SPFILE;

10.2 “write complete waits” 等待严重

现象:等待事件 write complete waitsfree buffer waits 频繁出现。

原因:DBWn 写入速度跟不上脏块产生速度。

修复

-- 1. 增加 DBWn 进程
ALTER SYSTEM SET db_writer_processes=4 SCOPE=SPFILE;

-- 2. 增大 Buffer Cache
ALTER SYSTEM SET db_cache_size=4G SCOPE=BOTH;

-- 3. 检查 I/O 子系统性能
-- 例如 ASM disk 性能、SAN 配置

-- 4. 调整检查点参数
ALTER SYSTEM SET fast_start_mttr_target=300 SCOPE=BOTH;

10.3 实例恢复时间过长

现象:STARTUP 后实例恢复耗时几分钟,影响可用性。

排查

-- 查看实际恢复时间
SELECT 
  recovery_estimated_ios,
  actual_redo_blks,
  fast_start_mttr_target_redo_blks
FROM v$instance_recovery;

-- 警报日志中查看:
-- Sun Jul 21 10:23:15 2026
-- Beginning crash recovery of 1 threads
-- Completed crash recovery at ...
-- (时间差 = 实际恢复时间)

修复

-- 1. 调小 MTTR 目标
ALTER SYSTEM SET fast_start_mttr_target=60 SCOPE=BOTH;

-- 2. 增加 DBWn 进程
ALTER SYSTEM SET db_writer_processes=4 SCOPE=SPFILE;

-- 3. 启用并行恢复
ALTER SYSTEM SET recovery_parallelism=4 SCOPE=SPFILE;

10.4 Redo Log 切换过快

现象:每分钟切换多次 Redo Log,性能下降。

排查

-- 查看日志切换历史
SELECT 
  to_char(first_time, 'YYYY-MM-DD HH24') AS hour,
  count(*) AS switches
FROM v$log_history
WHERE first_time > SYSDATE-1
GROUP BY to_char(first_time, 'YYYY-MM-DD HH24')
ORDER BY hour DESC;

-- 健康标准:每小时 < 3 次切换

修复

-- 1. 增加 Redo Log 大小
ALTER DATABASE ADD LOGFILE GROUP 4 ('/u01/redo04.log') SIZE 1G;

-- 2. 优化产生大量 Redo 的 SQL(批量操作改用 NOLOGGING)
ALTER TABLE large_tab NOLOGGING;
INSERT /*+ APPEND */ INTO large_tab SELECT * FROM source_tab;
ALTER TABLE large_tab LOGGING;

10.5 OFFLINE 表空间卡住

现象:执行 ALTER TABLESPACE users OFFLINE 长时间无响应。

原因:触发局部检查点,DBWn 写该表空间脏块速度慢。

修复

-- 1. 监控 DBWn 进度
SELECT event, total_waits, time_waited
FROM v$system_event
WHERE event LIKE '%checkpoint%';

-- 2. 加快检查点完成(暂时调小 MTTR)
ALTER SYSTEM SET fast_start_mttr_target=30 SCOPE=BOTH;

-- 3. 或使用 OFFLINE TEMPORARY(不触发完全检查点)
ALTER TABLESPACE users OFFLINE TEMPORARY;

10.6 SHUTDOWN IMMEDIATE 缓慢

现象SHUTDOWN IMMEDIATE 卡住几分钟才完成。

原因:触发完全检查点,DBWn 需要写所有脏块。

修复

-- 1. 提前手动触发检查点
ALTER SYSTEM CHECKPOINT;

-- 2. 等几秒后再 shutdown
SHUTDOWN IMMEDIATE;

-- 3. 调整参数加快关闭
ALTER SYSTEM SET fast_start_mttr_target=30 SCOPE=BOTH;

11. 最佳实践

11.1 使用 FAST_START_MTTR_TARGET

-- 推荐设置(根据业务 SLA)
-- OLTP: 60-120 秒
-- OLAP: 300-600 秒
ALTER SYSTEM SET fast_start_mttr_target=120 SCOPE=BOTH;

-- 关闭旧参数
ALTER SYSTEM SET log_checkpoint_interval=0 SCOPE=BOTH;
ALTER SYSTEM SET log_checkpoint_timeout=0 SCOPE=BOTH;

11.2 合理规划 Redo Log

-- 查看当前 Redo Log 配置
SELECT group#, bytes/1024/1024 AS mb, members, status 
FROM v$log;

-- 健康指标:
-- 1. 每组至少 1 个 member(推荐 2-3 个多路复用)
-- 2. 至少 3 个 group(推荐 4-6 个)
-- 3. 单组大小:每小时切换 3-5 次
-- 4. 大小估算:峰值 Redo 速率 × 30 分钟

估算 Redo 速率

-- 查看每小时 Redo 生成量
SELECT 
  to_char(first_time, 'YYYY-MM-DD HH24') AS hour,
  sum(blocks * block_size)/1024/1024/1024 AS redo_gb
FROM v$archived_log
WHERE first_time > SYSDATE-1
GROUP BY to_char(first_time, 'YYYY-MM-DD HH24')
ORDER BY hour DESC;

11.3 根据负载调整 DBWn 进程数

-- 监控 DBWn 等待
SELECT event, total_waits, time_waited
FROM v$system_event
WHERE event IN ('free buffer waits', 'write complete waits');

-- 如果等待明显,增加 DBWn
ALTER SYSTEM SET db_writer_processes=4 SCOPE=SPFILE;
-- 重启生效

-- 经验值:
-- 1-4 CPU: 1 个 DBWn
-- 8-16 CPU: 2-4 个 DBWn  
-- 32+ CPU: 4-8 个 DBWn

11.4 监控检查点进度

-- 定期检查实例恢复进度
SELECT 
  recovery_estimated_ios,
  actual_redo_blks,
  target_redo_blks
FROM v$instance_recovery;

-- actual_redo_blks 应该接近 target_redo_blks 的 50% 以下

11.5 启用检查点日志

ALTER SYSTEM SET log_checkpoints_to_alert=TRUE SCOPE=BOTH;
-- 便于排错,开销很小

11.6 ASM + 多 DBWn

对于使用 ASM 的高负载系统:

-- 1. 增加 DBWn
ALTER SYSTEM SET db_writer_processes=8 SCOPE=SPFILE;

-- 2. ASM 配置多 disk group 分散 I/O
-- DATA: 数据文件
-- FRA: 闪回区
-- REDO: Redo Log(单独 disk group 性能最佳)

-- 3. ASM AU 大小 4M(大数据库)
-- CREATE DISKGROUP DATA EXTERNAL REDUNDANCY 
--   DISK '/dev/asm*' ATTRIBUTE 'au_size'='4M';

11.7 关闭数据库前预 checkpoint

-- 维护窗口前
ALTER SYSTEM CHECKPOINT;
-- 等待几秒
ALTER SYSTEM SWITCH LOGFILE;
-- 再 SHUTDOWN
SHUTDOWN IMMEDIATE;

12. 参考资料

[1] Oracle Database Administrator’s Guide 19c, “Controlling Checkpoints” https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/controlling-checkpoints.html

[2] Oracle Database Concepts 19c, “Checkpoints” https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/checkpoints.html

[3] AskTOM, “Checkpoint Internals and FAST_START_MTTR_TARGET” https://asktom.oracle.com/pls/apex/f?p=100:1:0

[4] 墨天轮,“Oracle 检查点机制与实例恢复详解” https://www.modb.pro/db/1759656813559025664

[5] Oracle Support Note 147468.1, “Checkpoint Tuning and Troubleshooting Guide” https://support.oracle.com/epmos/faces/DocumentDisplay?id=147468.1

[6] Jonathan Lewis, “Oracle Core: Essential Internals for DBAs and Developers”(Apress, 2011)