Oracle SCN(System Change Number)机制详解

Oracle SCN(System Change Number)机制详解

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


1. 概述

SCN(System Change Number)是 Oracle 数据库内部的逻辑时钟,标识数据库某个一致状态的时间点[1]。

核心作用

  • 标记事务提交顺序
  • 实现读一致性(Read Consistency)
  • 控制实例恢复范围
  • Data Guard 同步位置标记

SCN 特性

  • 单调递增(不会回退)
  • 全局唯一(单实例 / RAC 全局一致)
  • 6 字节存储(理论最大 2^48)
  • 每次 COMMIT 推进

2. SCN 类型

类型含义查询视图
System Commit SCN最新提交的 SCNv$database.current_scn
Checkpoint SCN检查点推进到的 SCNv$datafile.checkpoint_change#
Datafile SCN数据文件头 SCNv$datafile_header.checkpoint_change#
Stop SCN控制文件中数据文件”停止 SCN”v$datafile.last_change#
Block SCN数据块最后修改 SCN数据块头
Undo SCNUndo 记录对应的 SCNv$transaction

3. SCN 推进机制

3.1 COMMIT 推进

每次事务 COMMIT 时,Oracle 分配一个新的 SCN:

-- 事务提交前查询
SELECT current_scn FROM v$database;
-- 1234567890

-- 执行事务并提交
INSERT INTO t VALUES (1);
COMMIT;

-- 提交后查询
SELECT current_scn FROM v$database;
-- 1234567895(推进了 5)

3.2 检查点推进

CKPT 进程每 3 秒或在检查点触发时推进 SCN:

SELECT name, checkpoint_change#, checkpoint_time 
FROM v$datafile;

3.3 心跳推进

每 6 秒一次心跳(即使无事务),将 SCN 写入控制文件。


4. SCN 与读一致性

Oracle 通过 SCN 实现 MVCC(多版本并发控制)[1][2]:

事务 T1(SCN=1000):查询 BEGIN
   SELECT * FROM emp WHERE id=1;

事务 T2(SCN=1005):UPDATE emp SET sal=5000 WHERE id=1;
                    COMMIT;

事务 T1 继续查询:
   - 当前数据块 SCN=1005 > T1 的查询 SCN=1000
   - 不能读当前块
   - 从 Undo 段中读取 SCN ≤ 1000 的 CR 块
   - 返回旧值
-- 查看当前 SCN
SELECT current_scn FROM v$database;

-- 闪回查询指定 SCN 的数据
SELECT * FROM employees 
AS OF SCN 1234567890 
WHERE id = 1;

5. SCN 与实例恢复

实例崩溃后,启动时通过 SCN 判断恢复范围:

启动检查:
1. 读取控制文件中每个数据文件的 Stop SCN
2. 读取数据文件头 SCN(即 Checkpoint SCN)
3. 若 Stop SCN = Checkpoint SCN:无需恢复
4. 若 Stop SCN < Checkpoint SCN:需要实例恢复

实例恢复:
1. 从 Checkpoint SCN 开始重做 Redo
2. 前滚到 On-Disk RBA 对应的 SCN
3. 打开数据库
4. 后台回滚未提交事务

查看状态

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

-- 比较 Stop SCN 和 Checkpoint 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
-- 异常关闭:stop_scn 为 NULL

6. SCN 限制(SCN Health)

Oracle 对 SCN 增长有速率限制,防止 SCN 过快耗尽[3]:

SCN Soft Limit:
  - 每秒最大推进: 16384(默认 _max_reasonable_scn_rate)
  - 超过会触发 ORA-00600: [kdsgrp1] 或 alert 警告

SCN Hard Limit:
  - 理论最大值: 2^48(约 281 万亿)
  - 19c 引入 SCN Headroom 检查

查询 SCN Headroom

SELECT 
  dbid,
  current_scn,
  scn_headroom,
 Reason
FROM v$sysmeta_history
WHERE name = 'SCN_HEADROOM';

-- 或使用 DBMS_SCN 包(12.2+)
EXEC DBMS_SCN.GET_SCN_SCN_HEADROOM(:headroom);

7. Data Guard 中的 SCN

主备库通过 SCN 同步:

-- 主库当前 SCN
SELECT current_scn FROM v$database;

-- Standby 应用到的 SCN
SELECT 
  thread#, 
  sequence#,
  applied_scn,
  resetlogs_change#
FROM v$archived_log
WHERE applied = 'YES'
ORDER BY sequence# DESC;

8. 常见坑与排错

8.1 ORA-00600: [kcbls_1] SCN 异常

现象:数据库 alert log 报 SCN 异常。

原因:SCN 推进过快,可能由于:

  • 跨平台 DG 同步问题
  • 老版本兼容性 bug
  • 使用了不当的隐藏参数

修复

-- 检查 SCN 健康度
EXEC DBMS_SCN.GET_SCN_SCN_HEADROOM(:h);
PRINT h;

-- 联系 Oracle Support,可能需要 patch

8.2 ORA-01555: snapshot too old

现象:长查询报 ORA-01555。

原因:查询 SCN 太旧,Undo 数据已被覆盖。

修复

-- 增大 undo_retention
ALTER SYSTEM SET undo_retention=3600 SCOPE=BOTH;

-- 启用 Undo 保留保证
ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;

8.3 RAC 中 SCN 不同步

现象:RAC 节点间 SCN 差异大。

修复:检查私有网络延迟,确保 LGWR 同步正常。


9. 最佳实践

  1. 不要手工修改 SCN:可能导致数据库不一致
  2. 定期监控 SCN HeadroomDBMS_SCN.GET_SCN_SCN_HEADROOM
  3. 长查询设置合理 undo_retention
  4. Data Guard 同步监控:定期对比主备 SCN
  5. 升级前检查 SCN 健康:避免升级后兼容性问题

10. 参考资料

[1] Oracle Database Concepts 19c, “Read Consistency” https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/data-concurrency-and-consistency.html

[2] AskTOM, “SCN Internals” https://asktom.oracle.com/pls/apex/f?p=100:1:0

[3] Oracle Support Note 1393360.1, “SCN Headroom” https://support.oracle.com/epmos/faces/DocumentDisplay?id=1393360.1