☰
alert log出现启动信息就是数据库重启?详解Oracle“假重启”现象与排查流程
2026/10/17 6:28:25 网站建设 项目流程

先说个让我印象挺深的巡检场景。某天中午我照例去翻生产环境的alert log,结果一眼就看到了“Starting ORACLE instance (normal)”,后面还跟着“Total System Global Area”、“DATABASE MOUNTED”、“Database opened”这一整套启动信息。第一反应当然是:糟糕,数据库是不是半夜挂了又自己拉起来了?赶紧查v$instance,结果数据库启动时间是两百多天前,业务侧也完全没感知。于是我对着alert log反复看了三遍,越想越不对劲——alert log明明有启动信息,数据库却没有重启,这到底是怎么发生的?

排查完一圈才知道,“启动信息”和“数据库重启”之间并不是等号。这中间藏着很多运维上容易踩的坑,尤其对RAC环境、带有集群自动拉起机制的库,还有经常有人手动startup的环境,误判的概率非常高。这篇文章就把这类“假重启”现象的来龙去脉讲清楚,顺便给出一套可以直接照搬的排查流程。

1. alert log里的启动信息是怎么写出来的

1.1 alert log的记录机制

alert log,也就是常见的alert_ .log,相当于数据库实例的“黑匣子”。它会按时间顺序记录实例生命周期相关的关键事件:实例启动、实例关闭、日志切换、检查点、表空间变更、坏块信息、ORA错误等。这些日志由Oracle的后台进程直接追加写入,使用的是纯文本格式,带时间戳,而且默认只保留一份,文件达到一定大小后会自动轮转生成历史文件。

正因为它是追加写的,理论上一个正在运行的实例,其alert log里出现“启动信息”,意味着某个进程在某个时刻确实发起过实例启动动作。这是整个问题的关键出发点——不是“数据库重启了”,而是“有一个启动动作发生了,需要查清楚是谁触发的,以及它有没有成功”。

很多新手会犯一个错误:只要在日志里搜到“Starting”就当成实例重启。实际上alert log里“Starting”开头的行有很多种,比如“Starting background process XXXX”指的是某个后台进程重新启动,和实例启动完全不是一个层级。

1.2 一次完整启动信息长什么样

以单实例为例,一次完整的启动日志一般长这样:

Thu Jun 15 03:27:11 2023 Starting ORACLE instance (normal) ____________________________ ... Total System Global Area 8589934592 bytes Fixed Size 8973408 bytes Variable Size 2013265920 bytes Database Buffers 6543114240 bytes Redo Buffers 19398656 bytes Database mounted. Database opened.

第一行是时间戳,第二行说明启动模式是normal(也可能是mount、open、force)。紧接着是SGA分配情况,然后是“Database mounted”和“Database opened”。如果只看到“Starting ORACLE instance”后面跟着一堆ORA错误,没有“mounted”和“opened”,那就意味着启动过程在中途失败了,数据库并没有成功重启。

这行信息本身就说明:只有有人执行了startup命令,或者某个自动化机制(CRS、dbstart、脚本)发起了startup,alert log才会记录。所以第一步不是先怀疑日志有问题,而是先确认这次启动动作来自哪里。

1.3 哪些动作会触发启动信息

结合我的经验,常见触发器有这些:

  • 有人手动执行了startup命令,包括sqlplus里执行、通过pluggable database方式启动指定实例。
  • 服务器重启后,Oracle集群软件(CRS)或dbstart脚本按配置自动把数据库拉起。
  • RAC环境中,集群检测到某个节点实例故障后自动重启该实例。
  • 实例发生crash后,通过某种恢复流程重新启动。
  • 某些运维脚本或监控脚本误触发了startup命令。

所以,问题本质上是“启动动作从哪来”。下面从实际排查顺序的角度,一步步拆开。

2. 排查第一步:先区分“实例重启”“数据库重启”和“主机重启”

2.1 三个概念不能混

运维圈子里经常把“实例重启”“数据库重启”“主机重启”混着说,实际含义差别很大,排查方向也完全不同。

  • 实例重启:指某个Oracle实例(内存结构+后台进程)重新启动。在RAC中,单个节点实例重启不代表整个数据库不可用。
  • 数据库重启:指整个数据库服务全部停掉再起来。对单实例来说,实例重启就是数据库重启;对RAC来说,通常是所有实例一起重启。
  • 主机重启:指物理机或虚拟机操作系统重启。主机重启后,通过集群或开机脚本自动拉起的数据库,会在alert log里留下启动信息,但看起来像“自己启动”了。

先把这个概念理清,后面排查思路才不歪。

2.2 用v$instance确认真实启动时间

听到“启动信息”,我第一件事是查数据库到底什么时候启动的:

select instance_name, instance_number, status, to_char(startup_time, 'yyyy-mm-dd hh24:mi:ss') as startup_time, host_name from v$instance;

如果startup_time和alert log里出现启动信息的时间戳对不上,那说明alert log里那一条根本不是这次实例的启动记录,或者是你比较的时间基准不对。

这里有个特别容易忽略的点:alert log的时间戳用的是操作系统时区,而v$instance.startup_time用的是数据库会话时区。有些环境操作系统是UTC,数据库却设置了东八区,直接拿去对比会差好几个小时,很容易得出错误结论。建议先执行select dbtimezone, sessiontimezone, systimestamp from dual;确认两边的时区,再统一换算。

2.3 查操作系统是否重启过

如果数据库确实没重启,那还有一种可能:主机重启过,但数据库在主机启动时被集群软件自动拉了起来。对业务来说,因为有应用层重连或RAC failover,用户感受不到;但从日志看,数据库确实经历了一次完整的重新启动。

判断方法很简单,在目标主机上执行:

who -b uptime last reboot

看系统启动时间是否与alert log启动信息时间吻合。如果吻合,那大概率是主机重启引发的自动拉起;如果不吻合,再把视线转向集群日志和人工操作记录。

3. 五种典型的“看起来重启但实际没重启”场景

3.1 后台进程自动重启,被误看成实例启动

这是我见过最多的一种误判。alert log里出现“Starting background process MMON”或“MMNL”之类的行,前面没有任何shutdown信息,数据库服务也一直正常。如果不逐字看,很容易把“Starting background process”和“Starting ORACLE instance”搞混。

出现这种日志,通常是某个后台进程因为内部异常退出后,被PMON自动拉起。比如MMON进程(管理性监控进程)在部分版本里有已知的异常重启现象,alert log里可能还会伴随ORA-00600之类的内部错误。但这只代表一个内存后台进程重新启动,和实例重启完全无关,更不影响数据库连接和业务。

排查时最有效的方法是看上下文:真正的实例启动前,通常会有Shutting down instance或上次实例终止的痕迹;而单个后台进程重启,前后一般都有正常运行的日志切换或告警报错,整个库的startup_time也不会改变。

3.2 startup失败留下的“启动痕迹”

另一个坑是“启动尝试”不等于“启动成功”。比如某个开发A同学手痒,登录服务器执行了sqlplus启动命令,但立刻发现权限不够、参数文件有问题或者实例已在其他节点运行,启动在中途被终止。alert log里依然会先写下“Starting ORACLE instance (normal)”和SGA分配信息,然后跟着一堆ORA错误,最后没有“Database opened”。

这种情况下,数据库其实一直在正常运行,但alert log里却留下了启动信息,形成一个“假重启”现场。

判断方法也很简单:看启动信息后面有没有“Database opened”。如果只是启动头几行,后面跟着ORA-01031、ORA-01565、ORA-16005之类的报错,那基本就是一次失败的启动尝试。数据库并没有重启,v$instance的startup_time也不会发生任何变化。

3.3 RAC单节点实例重启,整个数据库并未重启

RAC环境下更容易产生这种困惑。某个晚上节点2的实例因为网络心跳丢失、ORA-29701或CSSD重启等原因被集群自动拉起来,节点2的alert log里就会出现完整的启动信息;但节点1一直正常对外提供服务,业务侧没有数据库中断的感觉,监控告警也没触发“数据库不可用”。如果此刻只看节点2的alert log,很容易误以为整个数据库重启了。

这种场景下连业务方都会坚持说“数据库没重启”,因为确实没有停服务。但从运维角度,这是真实的“实例重启事件”,需要进一步排查为什么节点2会重启。典型排查命令包括:

crsctl stat res -t -v

重点看ora.xxx.db下各实例资源的状态,再翻集群告警日志、cssd日志和网络心跳检查结果。和“假重启”不同,这属于“部分节点真重启但服务未中断”的误读。

3.4 主机重启后集群自动拉起数据库

这是最容易让运维人员自我怀疑的一个场景。半夜机房断电或系统升级触发OS重启,主机启动后CRS按配置自动启动数据库实例,alert log里就会留下完整的启动信息。但因为RAC其他节点承担了全部流量,或者应用层做了重连,整个数据库从业务侧看就像没有重启过一样。

如果你在alert log里发现启动信息,但又确认当天没人执行过startup,同时v$instance的startup_time又确实被更新了,那就去查操作系统启动时间。执行last reboot,如果系统启动时间和数据库启动时间只差一两分钟,那基本就是主机重启后的自动拉起。

这类问题真正需要关注的是:为什么业务没感知?是RAC failover起作用了,还是应用层重连机制兜住了。对单实例环境来说,主机重启必然导致数据库重启,业务感知不到反而需要提高警惕。

3.5 alert log轮转或被清理造成的位置错觉

还有一种情况纯粹是“日志显示位置”造成的误导。alert log轮转后,新文件的第一行可能是某个重要事件,如果这个事件恰好是启动信息,而且单击打开文件时看到第一行就是它,就会误以为刚刚发生了重启。

更极端的是有人用echo或rm方式清空了alert log,之后新日志的第一行就是某次启动或日志切换信息,看起来特别像“重启现场”。

判断方法也简单:看alert log文件大小和创建时间,再检查同目录下有没有旧轮转文件(alert_1.log、alert_2.log等)。如果旧文件里没有对应启动痕迹,那基本是轮转从某个历史时间点延续下来的,说明启动信息发生在更早之前,而不是现在。

4. 现场排查实操流程

4.1 先从alert log里精准定位启动信息

拿到alert log后,我习惯分三步走。第一步是定位启动信息具体在哪一行:

grep -n "Starting ORACLE instance" alert_xxx.log grep -n "Starting ORACLE instance" alert_xxx.log | tail -20

第二步是看启动信息前后的上下文。用sed把附近的日志打出来:

sed -n '/Starting ORACLE instance/,+40p' alert_xxx.log

重点看启动信息前面是否有“Shutting down instance”或“Instance terminated”之类的关闭记录,启动信息后面是否有“Database opened”,以及之后紧接着发生的日志切换、告警事件是什么。如果启动信息后面直接出现了ORA错误,说明启动没有完成。

第三步是看启动信息的时间戳距离现在有多远。有时候它只是历史遗留,并不是最近发生的。很多人看到“txt里有一条Starting”就紧张,完全没注意到时间戳是三个月前的。

4.2 用数据库内部状态二次确认

日志只是线索,最终要以数据库实际状态为准。需要执行:

select instance_name, status, to_char(startup_time,'yyyy-mm-dd hh24:mi:ss') startup_time from v$instance; select program, background_process, count(*) from v$session group by program, background_process;

如果startup_time和alert log时间吻合,说明该实例确实经历过一次启动,接下来去查启动原因;如果不吻合,说明alert log里那条信息不属于当前实例生命周期,大概率是其他节点、其他时期,或者时区差异。

有个小技巧:如果担心时区问题,可以直接对比alert log的启动时间戳和数据库启动时刻附近的systimestamp,并把两者统一到UTC再比较。

4.3 接着查操作系统和集群层面

确认完实例状态之后,需要把范围扩大到主机和集群。主机侧可以执行:

uptime who -b last reboot | head -10 ps -ef | grep smon_xxx | grep -v grep

ps -ef里smon进程的启动时间如果和OS启动时间接近,说明是开机自启拉起;如果比OS启动时间晚很多,说明是人工或集群后续触发的。

RAC环境还要继续查集群状态:

crsctl stat res -t -v crsctl stat res ora.xxx.db -p

同时去Grid Infrastructure目录下找集群告警日志,常见路径是$GRID_HOME/log/ /alert/crsalert_ .log,以及cssd、evmd日志。集群日志里会清楚记录是哪个进程发起了实例重启,以及触发原因。

4.4 还原“谁动了手”

排除了自动机制之后,剩下一个方向是人工操作。虽然这步难度最高,但也不是完全无迹可寻。

  • 操作系统的登录记录:last、/var/log/secure、/var/log/auth.log,可以看到什么时间段有哪些账号登录。
  • 客户端的审计记录:如果开启了数据库审计,可以查:
    select os_username, username, action_name, returncode, to_char(timestamp,'yyyy-mm-dd hh24:mi:ss') ts from dba_audit_trail where action_name like '%STARTUP%' order by timestamp;
    不过需要提醒的是,startup动作发生在实例启动阶段,数据库审计通常帮不上多少忙,这个结果经常是空的。
  • Shell history:root或oracle用户的.bash_history有时能还原,但生产环境一般不建议依赖这个,因为多人共用账号时历史记录混在一起。

实际操作中,比较可靠的办法是翻变更记录或操作工单。如果有人动过数据库,理论上会有流程记录。如果没有任何记录,自动机制的概率就大幅上升。

4.5 把时间轴对齐,重建现场

排查这类问题,最有力的手段是时间轴对齐。我会做一张简单的表格,把以下几类时间点放到一起比较:

  • alert log里启动信息的时间戳。
  • v$instance.startup_time。
  • 操作系统启动时间(who -b / last reboot)。
  • 集群资源状态变更时间(crsctl stat res带的时间历史)。
  • 监控告警时间和业务故障反馈时间。

当这些时间点能相互咬合时,结论基本就出来了。比如alert log的启动时间、OS启动时间、集群agent拉起时间都指向同一个凌晨,那就是主机重启自动拉起;如果启动时间明显早于OS启动时间,且没有其他记录,大概率是人为操作。

5. 常见问题速查与避坑心得

5.1 问题速查表

现象常见原因关键判据
alert log出现“Starting background process MMON/MMNL”后台进程异常后自动重启无前序shutdown,v$instance.startup_time不变
出现完整启动信息但v$instance启动时间不匹配时区差异、其他节点日志、历史轮转日志统一时区后对比时间戳
启动信息后紧跟ORA错误,没有Database openedstartup失败或启动被中断实例一直运行,startup_time不变
启动信息前没有任何关闭信息实例崩溃后被自动拉起,或主机重启后自动启动结合OS启动时间和CRS日志确认
RAC单节点alert log有启动信息该节点实例故障重启其他节点正常,crs资源显示该实例曾offline/online
启动信息正好出现在新alert log文件开头日志轮转或文件被重建检查同目录旧alert log文件
启动信息时间戳是几天前甚至几个月前历史记录而已,不是近期事件对比当前时间,查看日志连续性

5.2 独家避坑心得

每次排查这种“假重启”现场,我自己的经验是:不要看到一个关键词就下结论,至少要看三样东西——启动信息前面有没有关闭记录,启动信息后面有没有Database opened,以及v$instance的startup_time。这三样一对比,大部分误判都能被挡在门外。

还有一个小技巧可以分享给做监控脚本的同学:与其监控“出现Starting ORACLE instance就告警”,不如把条件设置得更严格一点。比如在脚本里加一段:

grep -A 20 "Starting ORACLE instance" alert_xxx.log | grep -q "Database opened" || echo "启动未完成,仅记录"

真正要告警的是“启动完成”或“启动失败”这类明确状态,而不是一看到启动字样就触发。这样能显著减少夜里被日志误报叫醒的次数。

另外,建议每个重要库都建一个“启动时间基线”,每天定时采集v$instance.startup_time,存一张小表或监控系统里。一旦alert log里出现可疑启动信息,直接对照基线就能判断实例是否真的重启过,比临时翻日志效率高得多。

我踩过最深的坑,是某次只看了alert log的启动头,没往下翻到“Database opened”,就贸然判断“数据库没重启”,结果后来查出来其实实例确实重启过,只是因为时区问题让时间对不上,差点漏掉一次闪断事故。所以这类问题宁可多查两层,也不能凭第一眼感觉走。alert log里每一行启动痕迹背后,都有一个“为什么”,把那个为什么找出来,才算真正排查完毕。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询