本节摘要:Oracle 实例是一支各有分工的进程队伍:LGWR 管日志先落盘、DBWn 管脏页批量写出、CKPT 管检查点广播、SMON 与 PMON 分别收拾系统级与会话级的残局。本节按"一次 COMMIT 的流转"串起这支队伍,并用一份告警日志逐段阅读示范,把故障入口文档变成值班员的点名册。
生产 Linux 上执行 ps -ef | grep ora_,你会看到一排 ora_ 开头的进程:ora_lgwr、ora_dbw0、ora_ckpt、ora_smon、ora_pmon……这是实例的点名册。与它们配套的是告警日志(alert log)——实例的病历本:启动关闭、检查点、错误与跟踪文件路径全在里面。老版本的告警日志在后台转储目录的 alert 文件里,12c 起推荐用 ADRCI 工具查看。值班第一课:任何故障,先开告警日志再看别处。它不会告诉你根因,但会告诉你该去找哪个进程、哪个文件的麻烦。
**LGWR(日志写进程)**是全库纪律最严的进程。任何事务提交,LGWR 必须把重做日志缓冲里对应的记录写到在线重做日志并确认,然后才向客户端返回"提交成功"——顺序写在磁盘上极快,这个设计让持久性保证的成本低到可以忽略。LGWR 还会在每三秒、缓冲三分之一满等时机主动写出,所以它永远是最忙的那个。
**DBWn(数据库写进程)**干的活同样关键但脾气相反:它不着急。脏块(内存里改过、磁盘上还是旧值的数据块)由 DBWn 批量写回数据文件,触发时机包括检查点到来、缓冲区缓存不够用找空闲块等。批量排序写出让磁盘 I/O 效率最大化。注意分工:LGWR 写重做日志(顺序、必须快),DBWn 写数据文件(随机、可以批量慢慢来)——数据文件暂时落后不要紧,因为崩溃恢复时可以靠重做日志重演一切,这正是"日志先行"(Write-Ahead Logging)的精髓。
**CKPT(检查点进程)**在检查点发生时更新数据文件头与控制文件,记录"到这里为止的变更都已落盘"。检查点越频繁,崩溃恢复需要重演的重做越少(实例恢复越快),但运行期 I/O 压力越大——这是第 6 章系统级调优的一对核心取舍。
SMON 与 PMON 是两位清道夫。 SMON(系统监视)管实例崩溃后的恢复:重启实例时,它用在线重做日志前滚未落盘的变更、回滚未提交的事务。PMON(进程监视)管会话级残局:某个服务器进程异常死亡时,它回滚该进程的事务、释放锁与资源。没有它们,一次断电就是一次人工灾难。
**ARCn(归档进程)**只在归档模式下出现:在线重做日志组切换时,把满组的日志抄送成归档日志。没有归档,你只有崩溃恢复能力;有了归档,才有第 5 章的时间点恢复与 Data Guard。
把名册串起来的最好方式是跟踪一次提交:
看懂这张时序图,你就能回答一个经典面试题:为什么提交成功的数据不会丢?因为返回成功前,重做日志已在磁盘上;哪怕下一秒断电,SMON 重启实例时按重做日志前滚,脏块的修改一分不少地回来。也能回答它的孪生题:为什么数据文件损坏不能只靠重启?因为重做日志保护的是"未写完",不是"写坏了"。
背景。 周三上午,报表系统反馈批量作业变慢,同时有人喊"磁盘快满了"。值班员老陈打开告警日志,从头到尾翻了两千行——这是错误姿势,正确的读法只要三步。
操作。 第一步抓时间线:定位异常首个出现的时间戳,只看那个时刻前后各十行。第二步读错误码:发现连续多组 Checkpoint not complete 与 Cannot begin new log,配的还有 ORA-19815 警告归档区使用率 97%。第三步找关联:日志指明归档目标目录与当前日志组序列号。
-- 验证日志组切换频率(隐患的量化证据) SELECT sequence#, first_time, ROUND((first_time - LAG(first_time) OVER (ORDER BY sequence#)) * 24 * 60, 1) AS minutes_between FROM v$log_history ORDER BY sequence# DESC FETCH FIRST 12 ROWS ONLY;
结果。 切换间隔显示高峰期每 4 分钟切一组日志,而每组 1GB 的日志归档要 5 分钟——写入速度压过归档速度,检查点无法推进,DBWn 被迫等待,整库 I/O 排队。解读。 报表变慢只是症状,病根是重做日志组配置与归档吞吐失配。处置:日志组从 3 组扩到 6 组、每组加成员做多路复用(放到不同磁盘),归档区扩容并清掉过期备份集。当晚批量作业耗时回落到正常水位。变式。 若日志显示的是 LGWR waited for log file switch 而无归档积压,则问题指向日志组本身太小,扩成员而不必动归档。同一段日志,错误码组合不同,药方完全不同——这就是三步读法的价值:先分类,再动手。
⚠️ 常见坑:把告警日志当小说从头读到尾。日志里 99% 的行是正常启动与切换记录,从头读只会浪费时间。抓时间线、读错误码、找关联路径,三步之外的都是噪音。
问题一:告警日志要不要清空或轮转? 要轮转但不是清空:日志长期不转会让单个文件巨大且难检索,多数环境的做法是按月切割归档保留一年,切割动作脚本化。12c 之后的 ADRCI 自带按大小与时间的轮转策略,配置一次就不用再手工处理。
问题二:怎么给日志建立告警? 两层机制配合:实时层用脚本或监控代理扫描新增日志行,命中 ORA 错误码模式就触发告警;趋势层依赖指标(切换频率、检查点间隔)进监控面板。单靠"人想起来去看日志"的机制等于没有机制——日志的价值在它被自动读取之后才开始。
问题三:服务器进程和共享服务器模式怎么选? 绝大多数 OLTP 用专用服务器模式(一会话一进程,隔离好、诊断直);共享服务器(多会话复用进程池)只在海量轻连接、内存紧张的老场景有意义,且它让诊断复杂化(PGA 位置变化、会话调试受限)。新设计选共享服务器的理由,今天几乎都站不住。
本节要点回顾
进程队伍认识完,还剩最后一层现场:数据到底以什么形状躺在磁盘上。下一节拆物理文件与逻辑结构的对应关系。