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 | 最新提交的 SCN | v$database.current_scn |
| Checkpoint SCN | 检查点推进到的 SCN | v$datafile.checkpoint_change# |
| Datafile SCN | 数据文件头 SCN | v$datafile_header.checkpoint_change# |
| Stop SCN | 控制文件中数据文件”停止 SCN” | v$datafile.last_change# |
| Block SCN | 数据块最后修改 SCN | 数据块头 |
| Undo SCN | Undo 记录对应的 SCN | v$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. 最佳实践
- 不要手工修改 SCN:可能导致数据库不一致
- 定期监控 SCN Headroom:
DBMS_SCN.GET_SCN_SCN_HEADROOM - 长查询设置合理 undo_retention
- Data Guard 同步监控:定期对比主备 SCN
- 升级前检查 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