. Oracle 的后台进程
在本章开篇已经ᨀ到:Oracle 的实例(Instance)是指一组后台进程(在 Windows 上是一组
线程)和一块共享内存区域。图 1-2 即为 Oracle 数据库的实例概要图,可以看到实例的内存区
域 SGA 和一系列的后台进程示意(详细介绍将在后面章节逐步展开):
图 1-0-2 Oracle 实例示意图
《深入解析 Oracle》
·8·
通过上一节ᨀ到的日志信息,可以清晰的看到后台进程启动的过程,这里对于数据库运
行最为至关重要的进程主要有:PMON、DBWn、LGWR、CKPT、SMON、VKTM 等。如果
这些进程出现异常终止,则数据库将会崩溃。
下面简要介绍一些这些进程的作用。
PMON – 其全名为 Process Monitor – 进程监控进程,用于监控其他用户进程,当出现用
户进程失败时,执行进程恢复工作。PMON 的主要恢复职责在于释放失败进程未能正常释放
的内存锁和其他资源,如清理事务表状态等。
作为实例第一个启动的后台进程,PMON 还肩负监控其他 Oracle 后台进程的职责,在必
要时重启这些后台进程;此外,PMON 还负责向 TNS 监听器注册实例。
DBWn – 其全名为 DataBase Writer Process – 数据库写进程,有时也被写作 DBWR 进程,
该进程负责将内存中变更的数据写入磁盘数据文件。由于可以存在多个进程,所以增加 n 作
为后缀,虽然大多数情况下一个数据库写进程(DBW0)就足䭧了,但是 Oracle 允许配置最多
20 个写进程,名称为:DBW0~DBW9,DBWa~DBWj。对于多处理器的系统,多个 DBWR 进
程可以ᨀ升写性能。
DBWn 进程在满足以下条件时执行脏数据(Dirty Buffer)写出:
• 当一个 Server 进程扫᧿一定量的 Buffer 后仍然不能发现可用的 Buffer 时,通知
DBWn 执行写出;
• DBWn 会自动阶段性的执行写出,增进检查点。
由于内存中数据块的变更是零散的,所以 DBWn 执行批量写出才能有利于性能ᨀ升,
LGWR 进程通过日志写操作,延迟 DBWn 的写操作,从而实现了协同与性能促进。
LGWR – 其全名为 Log Writer Process – 日志写进程,LGWR 进程管理 SGA 中的 Redo
Log Buffer,将其中的内容连续写出到在线的日志文件中。Oracle 的 Redo 中记录的是可以重演
事务变更的必要信息,在事务ᨀ交时,日志必须写出到日志文件中。通过 LGWR 对于日志文
件的连续写出,就可以推延了 DBWR 对于脏数据的写出,从而保证 DBWR 可以实现批量写出
的性能ᨀ升。
在以下条件下,LGWR 将执行写出操作:
• 用户ᨀ交事务
• 在线日志发生切换(Log Switch)
• 距上次写操作 3 秒
• Redo Log Buffer 1/3 满或者具备 1 MB 数据
• 在 DBWn 执行写出前,需要确保相关 Dirty Buffer 的对应日志都已写出,此时会
通知 LGWR 写出此前未完成写出的相关日志。
CKPT – 其全名为 Checkpoint Process – 检查点进程,它负责更新控制文件和数据文件头
的检查点信息,CKPT 进程还会通知 DBWn 进程去执行写操作。检查点信息包括检查点位置、
SCN、Redo 的恢复位置等。
SMON – 其全名为 System Monitor Process – 系统监控进程,负责执行一系列的系统级别
的清理和其他工作,包括:
• 在数据库启动时,执行必要的实例恢复。在 RAC 数据库中,SMON 进程负责为
失败实例执行实例恢复。
第 1 章 数据库的启动和关闭
·9·
• 执行在实例恢复时跳过的中断事务,如由于读文件或表空间离线等错误,在实例
恢复时无法执行,SMON 则可以在表空间或文件在线时执行事务恢复。
• 回滚死事务,当一个进程异常中断,它的未ᨀ交事务就成为死事务,由 SMON 进
程负责回滚。
• 清理不再使用的临时段,例如当索引创建失败时产生的遗留临时段。
• 在字典管理表空间中,执行连续自由区间的合并。
• 维护 SMON_SCN_TIME 系统表。SMON_SCN_TIME 表记录了 SCN 与时间的对
应关系,由 SMON 定期进行定新,并将一些较老的数据定期删除。
• 维护 col_usage$数据字典表、维护 mod_mods$系统表。
• 定期 OFFLINE 多余的回滚段。
• 清理 obj$数据字典表中的垃圾数据。
VKTM – 其全名为Virtual Keeper of TiMe – 虚拟时钟进程,这个进程是在Oracle Database
11g 中引入的进程,用于ᨀ供一个数据库内部的虚拟时钟,以计算各种时间间隔量度等,VKTM
的引入降低和操作系统之间的交互,从而ᨀ高了性能。
VKTM 有两种运行模式:
• 基础模式,秒级间隔更新;
• 或者作为参考时间计数器,这种方式每 20 毫秒更新一次,仅在高优先级时可用。
对于不同的版本,VKTM 的设定模式可能不同,具体可以从告警日志文件中查知。
在 Oracle 11g 启动的过程中,信息ᨀ示:
K@)qu fgghg4usru5ovv,bVut cehbh>gu
在 Oracle 12c 中,信息ᨀ示:
K@)qubrs rc*uYhrDuth*[A-u.9uh*[oARvvusruclc7src*ut h> hr3
K@)qu fgghg4usru52vV,but cehbh>g
这个进程作为一个必选进程,对于数据库运行变得必不可少。
1.1.4. V$PROCESS 视图
细心的读者朋友通过前面的阅读或许已经注意到,在日志的进程启动信息里,并没有 pid=1
的进程,那么这个进程是否存在呢?
通过数据库中的 v$process 视图,可以找到对应于操作系统的每个进程信息:
9#=wubclcerus** -th*-bth*-fbc gs,c-t >4 s,uG >,u7dt >ecbbF
6SS0uuuuuuuuuuuu_iSu9_iSuuuuuuuU9'0n6q'u_0.y06q
BBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
TI'o%26Puuuuuuuuuuouuuuuuuuuuuuuuuuuuuuu_9'US.
TI'o%E%vuuuuuuuuuu2u%2Rvuuuuuuu> selcuuu> selcac34lcu5_q.nV
TI'o%'oNuuuuuuuuuuAu%2R2uuuuuuu> selcuuu> selcac34lcu5_9_vV
TI'o;APEuuuuuuuuuuNu%2RNuuuuuuu> selcuuu> selcac34lcu5qq6nV
TI'o;R;PuuuuuuuuuuTu%2R%uuuuuuu> selcuuu> selcac34lcu5S$(vV
TI'o;IAvuuuuuuuuuu%u%2REuuuuuuu> selcuuu> selcac34lcu5=y(0V
《深入解析 Oracle》
·10·
TI'oEN'Nuuuuuuuuuu;u%Avvuuuuuuu> selcuuu> selcac34lcu5P@_)V
mmmmmmmmm
注意以上输出,pid=1 的进程是一个 PSEUDO 进程,这个进程被认为是初始化数据库的
进程,启动其他进程之前即被占用,并在数据库中一直存在。通过 Oracle 的 oradebug 工具可
以稍微浏览一下这个进程的信息,以下是简要步骤,转储 SYSTEMSTATE:
9#=wue>ggceruMusbub3b*1s
P>ggcerc*m
9#=wu> s*c1f4ubcr,3th*
9rsrc,cgrut >ecbbc*m
9#=wu> s*c1f4u*f,tub3brc,brsrcuov
9rsrc,cgrut >ecbbc*m
9#=wubD>Yuts s,crc ufbc C*f,t
n6q' uuuuu)x_' K6=U'
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
fbc C*f,tC*cbr uuuuubr hg4 MroM> sroM*hs4M *1,bMrooo4M)ooo4Mr sec
在 user_dump_dest 目录中可以找到进程转储文件,其中进程 1 的信息如下,供读者参考:
_0.P'99uoQu
uuBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
uu9.QuvYgc Qu5ghlV-uGls4Quini)MBMBMve[vecbb-uGhlc[/bfmDu=in'Qo2%o%-ut4[v
uu5t >ecbbVu. selcuth*Qo-ubc Qv-uesllbuef Mr>tQu5ghlVM5ghlV
uuuuuuuuuuuuGls4buQu5v<2vVu_9'US.> Quv-ueslluc > Quv-ubcbbuc > Quv-ur uv
uuuuuuuuuuuuhgr uzfcfcQuc,tr3
uuuu/bf*ltuI6=9'usrul>esrh>gQuv
uu5t>bruhgG>V lsbrut>bru cech7c*Quvuvuv
uuuuuuuuuuuuuulsbrut>bru cech7c*Bl>esrh>gQun>ut>br
uuuuuuuuuuuuuulsbrut >ecbbur>ut>bru,cQug>gc
uuuuuuuuuuuuuulsbrut>brubcgrQuvuvuv
uuuuuuuuuuuuuulsbrut>brubcgrBl>esrh>gQun>ut>br
uuuuuuuuuuuuuulsbrut >ecbbut>brc*u13u,cQug>gc
uuuu5lsreDuhgG>VuYshrCc7cgr[vu1hrb[v
uuuu.M9uhgG>Qufbc Qu-urc ,Qu-u>bth*Quu5S'6SV
uuuu.9Suth*uhgG>QuUghecbbuth*Quv-uh,s4cQu_9'US.
uuuuBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
uuuu9.Quv<%vvveEAE-ur3tcQuT-u>Ygc Quve[5ghlV-ugs,c[/bbuts cgr-uGhlc[/bb2mDu=in'QoAE-ut4[v
uu_9.ueDhl*ubrsrcu>1|cerueDsg4cbuQ
Sf,tu>Gu,c,> 3uG >,uvuv selcac34lcu1*f,tpdutbuBcG:4 ctu> sC
> selcuuuu%2Rvuuuuuouuvuo2QN2u?uuuuuuuuvvQvvQvvu> sCt,>gCc34lc
> selcuuuu%2R2uuuuuouuvuo2QN2u?uuuuuuuuvvQvvQvvu> sCtbtvCc34lc
> selcuuuu%2RNuuuuuouuvuo2QN2u?uuuuuuuuvvQvvQvvu> sC,,sgCc34lc
> selcuuuu%2R%uuuuuouuvuo2QN2u?uuuuuuuuvvQvvQvvu> sC*1YvCc34lc
> selcuuuu%2REuuuuuouuvuo2QN2u?uuuuuuuuvvQvvQvvu> sCl4Y Cc34lc
> selcuuuu%Avvuuuu ouuvuo2QN2u?uuuuuuuuvvQvvQvvu> sCe/trCc34lc
mmmmmmmmm
如果在操作系统上发现某个进程表现异常(如占用很高的 CPU 资源),那么通过操作系
统上的 PID 和 V$PROCESS 视图中的 SPID 关联,就可以找到这个 OS 上的进程在数据库
内部的化身,从而可以进行进一步的跟踪诊断。
V$PROCESS 视图包含当前数据库中活动进程的相关信息,这些进程在操作系统上都存在
与之对应的 OS 进程。其中 LATCHWAIT 列代表进程当前正在等待的 LATCH 信息,
LATCHSPIN 则记录进程正在通过 SPIN 进行 LATCH 的竞争。Latch 通常被称为闩,是数据库
内部的串行锁机制,主要用来控制内存上的并发,在多处理器系统上,Oracle 进程通过自旋(spin)
来进行 Latch 争夺。
这个视图结构如下所示(Oracle 10gR2 版本):
9#=wu*cbeu7dt >ecbb
ns,cuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunfll?uuuu)3tc
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBB BBBBBBBBBBBBB
6SS0uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu06(5NV
_iSuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunUq$'0
9_iSuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuK60Pk6025o2V
U9'0n6q'uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuK60Pk6025oTV
9'0i6=juuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunUq$'0
)'0qin6=uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuK60Pk6025AvV
_0.y06quuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuK60Pk6025NEV
)06P'iSuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuK60Pk60252TTV
$6P@y0.UnSuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuK60Pk6025oV
《深入解析 Oracle》
·12·
=6)Pk(6i)uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuK60Pk6025EV
=6)Pk9_inuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuK60Pk6025EV
_y6CU9'SCq'quuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunUq$'0
_y6C6==.PCq'quuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunUq$'0
_y6CI0''6$='Cq'quuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunUq$'0
_y6Cq6!Cq'quuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunUq$'0
注意这里的 ADDR 字段代表的是进程的地址,进程的状态等信息在内存中记录,这个
ADDR 记录的正是这样的内存地址信息。ADDR 在数据库中(甚至是所有软件中)是非常重
要的,虽然通常并不会用到,但是深入理解这些知识有助于大家更好的了解 Oracle 数据库。
进程的地址(Address of process)进一步的被缩写为 PADDR,在 V$SESSION 视图中记
录的 PADDR 就是 V$PROCESS.ADDR 的进一步延伸,通过两者关联,可以向数据库进
一步深入。
如果向操作系统端延伸,则 SPID 代表的正是操作系统进程标识符(Operating system
process identifier),通过 SPID 和 OS 中看到的进程 PID 关联,就可以建立从操作系统到数据库
的关联。
所以 V$PROCESS 被认为是从操作系统到数据库的入口。此外,和 PGA 相关的几个
字段则记录了进程的 PGA 使用情况。
1.1.5. 从操作系统到数据库
在上一节我们ᨀ到,V$PROCESS 被认为是从操作系统到数据库的入口,而进入数据
库内部,进程需要创建会话(Session)执行数据库操作和访问,通常一个进程创建一个
会话,特殊情况下,一个进程也可以创建多个数据库会话。会话信息通过视图
V$SESSION 进行体现和管理。
V$SESSION 视图在不同版本中被不断增强,尤其是自 Oracle 10g 开始,整合了
V$SESSION_WAIT(会话正在发生的等待信息)视图。
我们来看一下,如何完成从系统到数据库内部的导引。以下是一个简单的诊断分析
案例,在故障时刻,通过 TOP 工具观察到,有两个操作系统进程占用了极高的 CPU 资
源:
dur>t
l>s*us7c s4cbQuuom%o-uuom2E-uuom2Tuuuuuuuuuuk9(6_89S$uuuuuuuuuuuuuovQTvQNN
o;2ut >ecbbcbQuo%vublccthg4-uou fgghg4-uAuW>,1hc-u%ubr>ttc*-u2u>guetf
P_UubrsrcbQuuuuu&uh*lc-uuuuu&ufbc -uuuuu&u/c gcl-uuuuu&uh>Yshr-uuuuu&ubYst
qc,> 3QuNmvyu csl-uomNyuG cc-uomRyubYstuhgufbc-uEmRyubYstuG cc
uuu_iS U9'0n6q'u)k0u_0unP'uu9i+'uuu0'9u9)6)'uuu)iq'uI=)9uuuuP_UuP.qq6nS
2vT2o > selcuuuuuouNvuuuvuuomEyuuom;yu fguuuuu%QA;uuuuvuN;m;;&u> selc
2vENT > selcuuuuuouNvuuuvuuomEyuuom;yuetfv2uuuvQNouuuuvuNvmRE&u> selc
第 1 章 数据库的启动和关闭
·13·
2vEN;u> selcuuuuuouTEuuuvuuomEyuuom;yublcctuuuvQvvuuuuvuuvmEN&u> selc
2v;Evu> selcuuuuuouNEuuuvuuomEyuuom;yublcctuuuvQv2uuuuvuuvmEA&u> selc
oTE2Eu> selcuuuuuouTEuuuvuuomEyuuom;yublcctuuuvQTEuuuuvuuvmTA&u> selc
这两个进程分别是 20521 和 20845.通过 PS 命令可以找到这两个进程更为详细的信息:
dutbuBcG:4 ctu2vT2o
uu> selcu2vRvRu2vE;TuuvuovQTvQTAutrbMovuuuvQvvu4 ctu2vT2o
uu> selcu2vT2ouuuuuouN;uovQNAQTRu?uuuuuuuu%QNTu> selc|bDbu5=.P6=[n.V
dutbuBcG:4 ctu2vENT
uu> selcu2vENTuuuuuouNNuovQTvQvvu?uuuuuuuuvQTTu> selc|bDbu5=.P6=[n.V
uu> selcu2vRoEu2vE;TuuvuovQTvQTRutrbMovuuuvQvvu4 ctu2vENT
这两个 LOCAL=NO 的进程显然是来自应用的远程连接,通过如下脚本,关联 V$PROCESS
视图和 V$SESSION 视图、V$SQLTEXT 视图,可以找出这个进程正在执行的 SQL 语句,这
里只需要一个“发动”条件,就是进程号(PID):
9'='P)uuuMH~u.0S'0'SuHM
uuuuuuuuubzlCrcgu1
uuuuuuuuuuuuu(k'0'u1mts** u[u59'='P)us**
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuI0.qu7dt >ecbbue
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(k'0'uembth*u[uJZth*JVV
.0S'0u$xuthcecu69P
M
注意这里我们涉及了 3 个视图,并应用其关联进行数据获取,核心逻辑分解如下:
1.首先输入一个 pid,这个 pid 即 Process id,也就是在 Top 或 ps 中看到的 PID。
2.通过 pid 和 v$process.spid 相关联我们可以获得 Process 的相关信息。
3.通过 v$process.addr 和 v$session.paddr 相关联,可以获得和 session 相关的所有信息。
4.再结合 v$sqltext,即可获得当前 session 正在执行的 SQL 语句。
可见通过 v$process 视图,我们得以把操作系统和数据库关联了起来