背景
客户的虚拟机上运行着一个非常"怀旧"的数据库Oracle 10g。说实话,现在还在用这个版本的,确实不多见了。 由于底层宿主机维护,虚拟机被重启。重启后,数据库却无法正常启动了。
故障现象
尝试启动数据库,报错如下:
sql
SQL> startup
ORACLE 例程已经启动。
Total System Global Area 805306368 bytes
Fixed Size 1251584 bytes
Variable Size 213911296 bytes
Database Buffers 583008256 bytes
Redo Buffers 7135232 bytes
数据库装载完毕。
ORA-00600: 内部错误代码, 参数: [2252], [3919], [2247675337], [], [], [], [], []
这是一个典型的 ORA-00600 内部错误,参数 [2252] 是关键线索。
排查过程
1. 查看alter日志
log
Sun May 27 08:08:50 2001
starting up 1 dispatcher(s) for network address '(ADDRESS=(PARTIAL=YES)(PROTOCOL=TCP)))'...
MMNL started with pid=12, OS id=4108
Sun May 27 08:08:50 2001
starting up 1 shared server(s) ...
Sun May 27 08:08:51 2001
ALTER DATABASE MOUNT
Sun May 27 08:08:55 2001
Setting recovery target incarnation to 4
Sun May 27 08:08:55 2001
Successful mount of redo thread 1, with mount id 1919352083
Sun May 27 08:08:55 2001
Database mounted in Exclusive Mode
Completed: ALTER DATABASE MOUNT
Sun May 27 08:08:56 2001
ALTER DATABASE OPEN
Sun May 27 08:08:56 2001
Errors in file d:\oracle\product\10.2.0\admin\jsyorcl\udump\jsyorcl_ora_2856.trc:
ORA-00600: 内部错误代码, 参数: [2252], [3919], [2247675337], [], [], [], [], []
ORA-600 signalled during: ALTER DATABASE OPEN...
从alter日志就看到这个记录时间不太对劲,很明显,系统时间被重置到了2001年 。
联想到这个2252错误在 Oracle 老版本(包括 10g)中比较经典,主要和 SCN(System Change Number) 检查有关。
原理分析
ORA-00600 [2252] 在 Oracle 10g 及更早版本中比较经典,主要和 SCN(System Change Number) 的校验机制有关。
Oracle 在打开数据库时,会拿当前记录的 SCN 与基于系统日期计算出的允许最大SCN 进行比较。
如果当前 SCN 大于 系统时间允许的最大SCN,就会触发 ORA-00600 [2252]。
常见触发场景:
- 数据库异常关闭(crash、电源故障、kill实例等)
- 服务器系统时间被人为调小(或重置后比上次关闭时的时间还早)
- 控制文件或数据字典中的SCN记录异常
计算验证
当前数据库记录的SCN
从报错参数可以看到:
- SCN WRAP =
3919 - SCN BASE =
2247675337
计算公式为:
SCN = WRAP * 2^32 + BASE
sql
SELECT 3919 * POWER(2, 32) + 2247675337 AS result from dual;
计算结果:
RESULT
----------------------------------------
16834224508361
根据日志中系统时间(2001年)计算允许的最大SCN
sql
select to_number(
((to_date('20010527 08:08:56','yyyymmdd hh24:mi:ss') - to_date('19880101','yyyymmdd')) * 24 * 3600 * 16 * 1024),
'999999999999999999'
) max_scn
from dual;
结果:
MAX_SCN
--------------
6929732993024
对比:
- 数据库当前SCN:
16834224508361 - 2001年允许最大SCN:
6929732993024
当前SCN 远大于 允许的最大SCN,因此数据库拒绝打开,抛出ORA-00600 [2252]。
解决方案
问题的本质是系统时间被意外调小了 ,导致数据库认为SCN"过大"。
解决方法很简单:将系统时间修改为正确的时间。
修改系统时间后,用当前时间重新计算允许的最大SCN:
sql
select to_number(
((sysdate - to_date('19880101','yyyymmdd')) * 24 * 3600 * 16 * 1024),
'999999999999999999'
) max_scn
from dual;
结果:
MAX_SCN
-------------------------
19796786511872
此时:
- 数据库当前SCN:
16834224508361 - 当前时间允许最大SCN:
19796786511872
当前SCN 小于 允许的最大SCN,条件满足,数据库可以正常启动。
操作总结
- 确认系统时间异常(alter日志中时间与真实时间不符)
- 计算当前数据库SCN(从ORA-00600参数中获取)
- 计算当前系统时间允许的最大SCN
- 修改系统时间为正确时间
- 重新启动数据库
sql
-- 修改系统时间(操作系统层面)
-- Linux: date -s "2024-xx-xx xx:xx:xx"
-- Windows: 手动调整或使用命令行
-- 然后启动数据库
SQL> startup

经验教训
- 老版本Oracle(尤其是10g)对系统时间非常敏感,时间跳变可能引发SCN校验失败。
- 虚拟机环境要特别注意时间同步,避免宿主机重启导致虚拟机时间回退。
- ORA-00600 [2252] 虽然看起来吓人,但往往是"假故障",冷静分析SCN与时间的关系就能快速定位。
- 这类故障不需要重建控制文件或做不完全恢复,修正时间即可解决。
查看更多文章,点击查看 服务器重启后数据库无法打开,记一次ORA-00600 [2252]故障修复记
关注我,学习更多的数据库知识!