Oracle检查点Checkpoint深度解析

Oracle 检查点(Checkpoint)深度解析


一、检查点是什么

检查点(Checkpoint) :一种同步机制 ,确保 Buffer Cache 中的脏块DBWR 写入数据文件,并把这个一致性时间点记录到数据文件头和控制文件中。

核心目的

复制代码
1. 缩短崩溃恢复时间 (Crash Recovery)
2. 让 Redo Log 可以被覆盖重用
3. 保证数据文件的"一致性时间点"标记

二、为什么需要检查点

Oracle 的写入策略:延迟写

复制代码
用户提交事务
    ↓
① Redo Log Buffer → Redo Log File (LGWR 立即同步)
    ↓
② Buffer Cache 中的数据块标记为"脏块"(Dirty Block)
    ↓
③ 提交完成,返回客户端  ✅
    ↓
   (异步,过一会儿)
   ↓
④ DBWR 把脏块写入数据文件 ← Checkpoint 触发

关键洞察

  • Redo Log 是同步写(保证不丢数据)
  • 数据文件是异步写(提高性能)

没有检查点会发生什么?

如果不强制把脏块写入数据文件:

复制代码
问题 1: 崩溃恢复时,需要从"无穷远"的过去 Redo Log 开始重放,恢复时间极长
问题 2: Redo Log 无法循环重用,磁盘空间无限增长
问题 3: 数据文件永远落后于实际数据,不一致

三、检查点的内部机制

涉及的核心后台进程

复制代码
┌─────────────────────────────────────────────────┐
│                    Oracle Instance               │
│                                                 │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐  │
│  │   CKPT   │ →  │   DBWR   │ →  │   LGWR   │  │
│  └──────────┘    └──────────┘    └──────────┘  │
│    检查点进程     写脏块进程      写日志进程     │
│       │              │               │           │
│       ↓              ↓               ↓           │
│  更新控制文件   写入数据文件     写入日志文件     │
│  和数据文件头                                    │
└─────────────────────────────────────────────────┘
进程 职责
CKPT 触发检查点,更新控制文件和数据文件头不写脏块
DBWR Buffer Cache 中的脏块写入数据文件
LGWR Redo Log Buffer 写入 Redo Log 文件

⚠️ 常见误解 :CKPT 进程不写数据 !它只是通知 DBWR 写脏块 ,并更新控制文件


四、SCN:检查点的核心标识

SCN(System Change Number):Oracle 内部全局递增的时钟,标识数据库的每个状态变化。

复制代码
SCN = 1000  → 事务 A 提交
SCN = 1001  → 事务 B 提交
SCN = 1002  → Checkpoint 完成 ← 记录到控制文件
SCN = 1003  → 事务 C 提交
SCN = 1004  → Checkpoint 完成

检查点的几个关键 SCN

SCN 类型 含义
System Checkpoint SCN 数据库级别检查点 SCN,记录在控制文件
Datafile Checkpoint SCN 每个数据文件的检查点 SCN,记录在控制文件
Start SCN 数据文件头记录的 SCN,启动时校验
Stop SCN 数据库关闭时记录的 SCN
Checkpoint Progress SCN 当前正在进行的检查点位置

查看 SCN

sql 复制代码
-- 当前数据库 SCN
SELECT CURRENT_SCN FROM V$DATABASE;

-- 系统检查点 SCN
SELECT CHECKPOINT_CHANGE# FROM V$DATABASE;

-- 各数据文件检查点 SCN
SELECT FILE#, NAME, CHECKPOINT_CHANGE#
FROM V$DATAFILE
ORDER BY FILE#;

-- 数据文件头的 Start SCN
SELECT FILE#, NAME, CHECKPOINT_CHANGE#
FROM V$DATAFILE_HEADER;

启动数据库时,三个 SCN 必须全部一致才能正常打开:

复制代码
控制文件中的 System Checkpoint SCN
    ===
控制文件中的 Datafile Checkpoint SCN
    ===
数据文件头的 Checkpoint SCN

否则会触发实例恢复(Instance Recovery)介质恢复(Media Recovery)


五、检查点类型

Oracle 有多种检查点,触发条件和影响范围不同:

1. 完全检查点(Full Checkpoint)

触发

  • ALTER SYSTEM CHECKPOINT
  • 数据库正常关闭(SHUTDOWN NORMAL/IMMEDIATE
  • ALTER DATABASE BEGIN BACKUP(10g 前)

行为 :把 Buffer Cache 所有脏块写入数据文件。

sql 复制代码
-- 手动触发完全检查点
ALTER SYSTEM CHECKPOINT;

2. 增量检查点(Incremental Checkpoint)⭐ 默认机制

触发 :自 Oracle 8i 起的默认机制 ,由 CKPT 进程持续后台运行

行为

  • 不是一次性写完所有脏块
  • 而是持续地、增量地推进检查点位置
  • 用一个"RBA(Redo Byte Address)"指针追踪进度

优势

  • ✅ 避免完全检查点带来的性能尖峰(IO 抖动)
  • ✅ 平滑写入,IO 负载稳定

3. 日志切换检查点(Log Switch Checkpoint)

触发 :Redo Log 文件切换时(ALTER SYSTEM SWITCH LOGFILE)。

行为:写入被切换的日志组所"保护"的所有脏块。

sql 复制代码
-- 手动切换日志
ALTER SYSTEM SWITCH LOGFILE;

4. 表空间检查点(Tablespace Checkpoint)

触发

  • ALTER TABLESPACE ... OFFLINE NORMAL
  • ALTER TABLESPACE ... BEGIN BACKUP
  • ALTER TABLESPACE ... READ ONLY

行为:只写该表空间相关的脏块。

5. 对象检查点(Object Checkpoint)

触发

  • DROP TABLE
  • TRUNCATE TABLE
  • 索引重建等

行为:只写涉及该对象的脏块。

6. 并行查询检查点(Parallel Query Checkpoint)

触发:并行直接路径读取(Direct Path Read)前。

原因 :直接路径读取绕过 Buffer Cache,必须先把相关脏块刷盘。


六、控制检查点的关键参数

1. FAST_START_MTTR_TARGET(首选)⭐

含义:期望的最大崩溃恢复时间(秒)。

sql 复制代码
-- 设置崩溃恢复目标为 300 秒
ALTER SYSTEM SET FAST_START_MTTR_TARGET = 300;
  • 值越小,检查点越频繁,IO 越多,但恢复越快
  • 值越大,检查点越稀疏,IO 少,但恢复时间长
  • 推荐值:60 ~ 300 秒
sql 复制代码
-- 查看实际效果(MTTR 估算)
SELECT TARGET_MTTR, ESTIMATED_MTTR,
       CKPT_BLOCK_WRITES, LOG_FILE_SIZE_REDO_BLKS
FROM V$INSTANCE_RECOVERY;

2. LOG_CHECKPOINT_TIMEOUT(旧参数)

含义:检查点最大间隔时间(秒),0 表示禁用。

sql 复制代码
-- 1800 秒检查点一次
ALTER SYSTEM SET LOG_CHECKPOINT_TIMEOUT = 1800;
-- 0 = 禁用基于时间的检查点

3. LOG_CHECKPOINT_INTERVAL(旧参数)

含义:每多少 Redo Log 块触发一次检查点,0 表示禁用。

sql 复制代码
-- 每写 10000 个 OS 块(每块 512 字节)后触发
ALTER SYSTEM SET LOG_CHECKPOINT_INTERVAL = 10000;

4. LOG_CHECKPOINTS_TO_ALERT

含义:是否把检查点信息写入 alert.log。

sql 复制代码
-- 启用,便于监控
ALTER SYSTEM SET LOG_CHECKPOINTS_TO_ALERT = TRUE;

七、监控检查点

1. V$INSTANCE_RECOVERY(最重要)⭐

sql 复制代码
SELECT
    RECOVERY_ESTIMATED_IOS   AS "恢复需 IO 次数",
    ACTUAL_REDO_BLKS         AS "实际 Redo 块数",
    TARGET_REDO_BLKS         AS "目标 Redo 块数",
    LOG_FILE_SIZE_REDO_BLKS  AS "日志文件大小(块)",
    LOG_CHKPT_TIMEOUT_REDO_BLKS  AS "超时阈值",
    LOG_CHKPT_INTERVAL_REDO_BLKS AS "间隔阈值",
    FAST_START_IO_TARGET_REDO_BLKS AS "FAST_START_MTTR 阈值",
    TARGET_MTTR              AS "目标恢复时间(秒)",
    ESTIMATED_MTTR           AS "预估恢复时间(秒)",
    CKPT_BLOCK_WRITES        AS "检查点写入次数"
FROM V$INSTANCE_RECOVERY;

2. alert.log 中的检查点信息

启用 LOG_CHECKPOINTS_TO_ALERT=TRUE 后,告警日志会出现:

复制代码
Thu Apr 29 14:30:00 2026
Beginning log switch checkpoint up to RBA [0x35.2.10], SCN: 12345678
Thread 1 advanced to log sequence 53
  Current log# 2 seq# 53 mem# 0: /u01/oradata/orcl/redo02.log
Completed checkpoint up to RBA [0x35.2.10], SCN: 12345678

3. 等待事件诊断

sql 复制代码
-- 检查点相关的等待事件
SELECT EVENT, TOTAL_WAITS, TIME_WAITED, AVERAGE_WAIT
FROM V$SYSTEM_EVENT
WHERE EVENT IN (
    'log file switch (checkpoint incomplete)',  -- 严重!
    'checkpoint completed',
    'write complete waits',
    'free buffer waits',
    'log file switch completion'
)
ORDER BY TIME_WAITED DESC;

关键等待事件

等待事件 含义 处理
log file switch (checkpoint incomplete) 切换日志时上次检查点未完成,阻塞写入 增大日志文件、加快检查点
write complete waits 等待 DBWR 完成写入 DBWR 性能瓶颈
free buffer waits 等待空闲缓冲区 加大 Buffer Cache 或更频繁检查点

4. 监控检查点进度

sql 复制代码
SELECT
    FILE#,
    CHECKPOINT_CHANGE#,
    CHECKPOINT_TIME,
    LAST_CHANGE#
FROM V$DATAFILE
ORDER BY CHECKPOINT_TIME DESC;

八、检查点与崩溃恢复

崩溃恢复流程

复制代码
数据库崩溃
    ↓
重启实例 (STARTUP)
    ↓
读取控制文件中的 Checkpoint SCN (例如 SCN=1000)
    ↓
扫描 Redo Log,从 SCN=1000 之后的所有 Redo
    ↓
前滚 (Roll Forward): 重放所有 Redo,把数据库恢复到崩溃时刻
    ↓
打开数据库 (OPEN)
    ↓
回滚 (Roll Back): 利用 Undo 回滚未提交的事务
    ↓
恢复完成,可用

检查点频率与恢复时间

复制代码
检查点频繁    → Redo Log 中"未应用"的部分少 → 恢复快  → IO 多
检查点稀疏    → Redo Log 中"未应用"的部分多 → 恢复慢  → IO 少

配置建议

sql 复制代码
-- 期望最长恢复时间 60 秒
ALTER SYSTEM SET FAST_START_MTTR_TARGET = 60;

-- 关闭老参数,避免冲突
ALTER SYSTEM SET LOG_CHECKPOINT_TIMEOUT = 0;
ALTER SYSTEM SET LOG_CHECKPOINT_INTERVAL = 0;

-- 启用 alert 监控
ALTER SYSTEM SET LOG_CHECKPOINTS_TO_ALERT = TRUE;

九、常见问题与调优

问题 1:log file switch (checkpoint incomplete) 严重

现象

复制代码
Thread 1 cannot allocate new log, sequence 100
Checkpoint not complete

原因

复制代码
Redo Log 写满,要切换到下一组
    ↓
但下一组的脏块还没被 DBWR 写完(检查点未完成)
    ↓
LGWR 被迫等待,业务事务也被阻塞 ❌

解决

sql 复制代码
-- 方案 1: 增大 Redo Log 文件大小(推荐)
-- 让单个日志能撑更久,给检查点更多时间
ALTER DATABASE ADD LOGFILE GROUP 4
    ('/u01/oradata/orcl/redo04.log') SIZE 2G;

-- 方案 2: 增加 Redo Log 组数
-- 从 3 组增加到 5 组

-- 方案 3: 加快检查点(更频繁,平滑写入)
ALTER SYSTEM SET FAST_START_MTTR_TARGET = 60;

-- 方案 4: 提升 DBWR 性能(增加 DBWR 进程数)
ALTER SYSTEM SET DB_WRITER_PROCESSES = 4 SCOPE=SPFILE;
-- 需要重启

-- 方案 5: 优化 IO 性能(放在更快的存储)

问题 2:检查点导致的 IO 抖动

现象:业务平稳运行时,每隔一段时间 IO 突增。

解决

  • 使用 FAST_START_MTTR_TARGET(默认增量检查点)
  • 不要使用老的 LOG_CHECKPOINT_INTERVALTIMEOUT

问题 3:DBWR 写入慢

sql 复制代码
-- 检查 DBWR 是否成为瓶颈
SELECT EVENT, TOTAL_WAITS, TIME_WAITED
FROM V$SYSTEM_EVENT
WHERE EVENT LIKE 'db file%write%'
   OR EVENT IN ('free buffer waits', 'write complete waits');

优化

  • 增加 DB_WRITER_PROCESSES(默认按 CPU 核数自动计算)
  • 使用异步 IO(DISK_ASYNCH_IO=TRUE
  • 优化存储 IO 性能

问题 4:实例恢复时间过长

sql 复制代码
-- 测量恢复时间
SELECT ESTIMATED_MTTR, TARGET_MTTR
FROM V$INSTANCE_RECOVERY;

-- 如果预估值 > 业务可接受值,调小 FAST_START_MTTR_TARGET

十、检查点全流程图解

复制代码
事务执行阶段:
─────────────────────────────────────────────────────
  T1 INSERT  →  Redo Buffer  →  Buffer Cache(脏块)
  T2 UPDATE  →  Redo Buffer  →  Buffer Cache(脏块)
  T1 COMMIT  →  LGWR 同步写 Redo Log  ✅ 提交完成
─────────────────────────────────────────────────────


检查点触发:
─────────────────────────────────────────────────────
  ① CKPT 进程发起检查点(基于 FAST_START_MTTR_TARGET)
        ↓
  ② DBWR 把 Buffer Cache 的脏块写入数据文件
        ↓
  ③ DBWR 完成后通知 CKPT
        ↓
  ④ CKPT 更新控制文件: 记录新的 Checkpoint SCN
        ↓
  ⑤ CKPT 更新所有数据文件头: 记录新的 Checkpoint SCN
        ↓
  ⑥ 检查点完成,这之前的 Redo 可以被覆盖重用
─────────────────────────────────────────────────────


崩溃恢复:
─────────────────────────────────────────────────────
  实例崩溃 → 重启
        ↓
  读取控制文件的 Checkpoint SCN = X
        ↓
  扫描 Redo Log 中 SCN > X 的所有记录
        ↓
  前滚: 重放 Redo 到崩溃时刻
        ↓
  打开数据库
        ↓
  回滚: 用 Undo 回滚未提交事务
        ↓
  恢复完成
─────────────────────────────────────────────────────

十一、检查点与 RAC

RAC 环境中,检查点机制略有不同:

全局检查点

  • 每个实例独立进行检查点
  • GCS(Global Cache Service) 协调跨节点的脏块所有权
  • 通过 PI(Past Image) 机制保证一致性

关键差异

sql 复制代码
-- RAC 中查看各节点检查点
SELECT INST_ID, CHECKPOINT_CHANGE#
FROM GV$DATABASE
ORDER BY INST_ID;

-- 各节点恢复时间
SELECT INST_ID, ESTIMATED_MTTR, TARGET_MTTR
FROM GV$INSTANCE_RECOVERY;

十二、检查点 vs 提交(重要区分)

概念 触发者 作用对象 频率
COMMIT 用户事务 Redo Log Buffer → Redo Log File 每个事务
Checkpoint CKPT 进程 Buffer Cache 脏块 → Data File 周期性
复制代码
COMMIT     ≠   Checkpoint
持久化保证       一致性时间点标记

提交时:
  - Redo Log 立即落盘 ✅
  - 数据文件 不一定落盘 ❌(依赖 Checkpoint)

只要 Redo Log 安全,数据就不会丢:
  即使数据文件没更新,崩溃后重放 Redo 也能恢复

十三、面试常见问题

Q1: 为什么 COMMIT 不直接写数据文件?

A:性能。Redo Log 是顺序写(快),数据文件是随机写(慢)。先快速持久化 Redo,再异步批量写数据文件,整体性能更好。

Q2: 增量检查点 vs 完全检查点?

A

  • 增量检查点:持续平滑写入,默认机制,避免 IO 抖动
  • 完全检查点:一次性把所有脏块写完,只在关闭数据库等特殊场景

Q3: 检查点完成的标志是什么?

A:控制文件的 Checkpoint SCN 和所有数据文件头的 Checkpoint SCN 全部更新一致。

Q4: FAST_START_MTTR_TARGET 设小好还是大好?

A :根据业务对崩溃恢复时间的容忍度。一般 OLTP 建议 60~300 秒。设置过小会导致检查点过于频繁,增加 IO 负担。

Q5: 什么是检查点 RBA?

A:Redo Byte Address,标识 Redo Log 中的位置。检查点 RBA 表示"这个位置之前的脏块都已经写入数据文件"。


一句话总结

检查点是 Oracle 在性能(异步写)和安全(崩溃可恢复)之间的平衡机制

  • 作用:把 Buffer Cache 的脏块同步到数据文件,并记录一致性时间点(SCN)到控制文件和数据文件头
  • 目的:① 缩短崩溃恢复时间;② 让 Redo Log 可循环重用;③ 维持数据文件一致性
  • 机制 :默认是增量检查点,由 CKPT 持续后台推进;DBWR 真正写脏块,CKPT 只更新元数据
  • 关键参数FAST_START_MTTR_TARGET(推荐 60~300 秒)控制检查点频率
  • 核心监控 :关注 log file switch (checkpoint incomplete) 等待事件,出现就要调大 Redo Log 或加快检查点

记住核心公式:检查点 = 脏块刷盘 + SCN 同步标记 ,COMMIT 只保证 Redo 落盘,数据落盘靠检查点

相关推荐
￰meteor5 小时前
【数据库导学】
数据库
rising start5 小时前
三、深入理解MySQL索引底层
数据库·mysql
weixin_426150705 小时前
AI辅助Oracle容量规划:告别拍脑袋扩容
运维·数据库·人工智能·oracle
l1t5 小时前
DeepSeek总结的PostgreSQL 表访问方法
数据库·postgresql
数据库小学妹5 小时前
CTE+阶段式递归:用公共表表达式搞定复杂业务逻辑,告别SQL难题!
数据库·经验分享·b树·sql
UtopianCoding5 小时前
数据库语法对比详细规则
数据库·mysql·gaussdb
KaMeidebaby5 小时前
卡梅德生物技术快报|多肽库筛选:基于全质粒 PCR 的噬菌体文库构建与小分子表位淘选实战
前端·数据库·其他·百度·新浪微博
phltxy5 小时前
Redis 常见面试题
数据库·redis·缓存
IpdataCloud5 小时前
IP查询工具怎么选?在线API vs IP离线库:精度、速度、成本、隐私全对比
服务器·网络·数据库