实例后台进程在启动实例时启动,在终止实例时终止运行。
SMON
SMON(system monitor)起初的任务是安装和打开数据。SMON通过查找和验证数据库控制文件来安装数据库。此后,它通过查找和验证所有数据文件和联机日志文件,来打开数据库。一旦打开数据库并使数据库处于使用状态后,SMON就负责执行各种内部管理任务,如合并数据文件中的可用空间。
系统监视器(System Monitor)要完成所有“系统级”任务。PMON感兴趣的是单个的进程,而SMON与之不同,它以系统级为出发点,这是一种数据库“垃圾收集器”。SMON所做的工作包括以下几种:
- 清理临时空间:例如,建立一个索引时,创建时为索引分配的区段标记为TEMPORARY。如果处于某种原因CREATE INDEX会话中止了,SMON就要负责清理。其他操作创建的临时区段也要有SMON负责清理。
- 合并空闲空间:如果你在使用字典管理的表空间,SMON要负责取得表空间中相互连续的空间区段,并把它们合并为一个更大的空闲区段。只有当字典管理的表空间有一个默认的存储子句,而且pctincrease设置为一个非0值时,才会出现空闲空间的合并。
- 针对原来不可用的文件恢复活动的事务:这类似与数据库启动时SMON的作用。在实例/崩溃恢复时由于某个文件(或某些文件)不可用,可能会跳过一些失败的事务(即无法恢复),这些失败事务将由SMON来恢复。例如,磁盘上的文件可能不可用或未装载,当文件确实可用是,SMON就会由此恢复事务。
- 执行RAC中失败节点的实例恢复:在一个Oracle RAC配置中,集群中的一个数据库实例失败时(例如,实例所在主机失败),集群中的另外某个节点会打开该失败实例的重做日志文件,并为该失败实例完成所有数据的恢复。
- 清理OBJ$:OBJ$是一个低级数据字典表,其中几乎对每个对象(表、索引、触发器、视图等)都包含一个条目。很多情况下,有些条目表示的可能是已经删除的对象,或者表示“not there”对象(“not there”对象是Oracle一来机制中使用的一种对象)。要有SMON进程来删除这些不再需要的行。
- 收缩回滚段:如果有设置,SMON会自动将回滚段收缩为所设置的最佳大小。
- “离线”回滚段:DBA有可能让一个有活动事务的回滚段离线(offline),或置为不可用。也有可能活动事务会使用离线的回滚段。在这种情况下,回滚段并没有真正离线;它只是标记为“简要离线”。在后台,SMON会定期尝试真正将其置为离线,知道成功为止。
除此之外,它还会做许多其他的事情,如将DBA_TAB_MONITIRING视图中的监视统计信息刷新输出,将SMON_SCN_TIME表中的SCN-时间戳映射信息刷新输出,等等。随着时间的推移,SMON进程可能会累计地占用大量CPU时间,这应该是正常的。SMON会定期地醒来(或者被其他后台进程唤醒),来执行这些维护工作。
PMON
用户会话是连接到服务器进程的用户进程。服务器进程在此会话创建时启动,在会话结束时销毁。从会话中有序退出涉及用户注销。在这种情况下,用户执行的任何工作都将有序完成,服务器进程将终止。如果以无序方式终止会话(可能是用户计算机重新启动),那么会话将处于一个必须进行清理的状态。PMON(process monitor)监视所有服务器进程,并检测会话中的任何问题。如果会话异常终止,PMON将销毁服务器进程,将其PGA内存返回给操作系统的空闲内存池,并回滚任何尚在进行的未完成事务。
进程监视器(Process Monitor)负责在出现异常中止的连接之后完成清理,还负责监视其他的Oracle后台进程,并在必要时重启这些后台进程,也可能适当地中止实例。PMON还会为实例做另一件事,这就是向Oracle TNS监听器注册这个实例。实例启动时,PMON进程会询问公认的端口地址(1521),来查看是否启动并运行了一个监视器。如果数据库实例启动时有监听器在运行,PMON会与这个监听器通信,并向它传递相关的参数,如服务名和实例的负载度量等。如果监听器未启动,PMON则会定期地试图与之联系来注册实例。(12c中由LREG来实现此功能)
DBWn
会话通常并不将数据写入磁盘。会话将数据(或现有数据的更改)写入数据库缓冲区缓存中的缓冲区。由数据库写入器负责随后将缓冲区写入磁盘。一个实例可能有多个数据库写入器(最多不超过100个),一次称为DBW0到DBW9,然后是DBWa到DBWz,超过36的写入器命名为BW36到BW99。默认数量是每8个CPU对应一个数据库写入器(向上舍入)。在以下4种情况下,DBWn将执行写操作:没有任何可用缓冲区、脏缓冲区过多、遇到三秒超时或遇到检查点。
没有任何可用缓冲区的情况:如果服务器进程需要将块复制到数据库缓冲区缓存中,首先必须查找空闲的缓冲区。这种缓冲区是指既不脏(更新过,但尚未写回磁盘)也未被占用(即相应时刻正被另一个会话使用)的缓冲区。不能重写脏缓冲区,否则将丢失已更改的数据,也不能重写被占用的缓冲区,因为操作系统的内存保护机制不允许这么做。如果服务器进程超找空闲缓冲区用时过长(具体时限由Oracle内部确定),就会通知DBWn将某些脏缓冲区写入磁盘。一旦完成,缓冲区就是干净的,也就有了空闲的缓冲区可用。
脏缓冲区过多:这是由另一个内部阈值确定的。
遇到三秒超时:DBWn没三秒钟会对一些缓冲区清理一次。在实践中,这对生产系统影响不大,因为前面描述的两种情况将强制执行写入,但超时意味着:即使系统处于闲置状态,最终也会清理数据库缓冲区缓存。
可能存在请求的检查点:前面列出的三个原因将导致DBWn将有限数量的脏缓冲区写入数据文件。而当遇到检查点时,会写入所有脏缓冲区。因前三个原因而写入缓冲区称为增量检查点,或提高增量检查点位置。这是在正常运行过程中应该执行的,并进行优化,使缓冲区根据需要来提供,而不会给I/O系统增加压力,而影响了性能。这意味着可能有几十万个脏缓冲区。在检查点期间,磁盘I/O数量将达到顶峰,CPU使用率可能高达100%,最终用户会话的性能将下降。当完成检查点后(这可能需要数分钟的时间),性能将恢复到通常的状态。唯一绝对需要检查点的时刻是:关闭了数据库,关闭了实例。检查点将多有脏缓冲区写入磁盘:这就实现了缓冲区缓存与数据文件的同步,实例与数据库的同步。在通常的运行状态下,数据文件始终是过时的:它们缺少多个更改(提交的更改或未提交的更改)。这不会带来问题:因为缓冲区缓存中的数据块副本是最新的,而会话使用的正是这些数据块。在关闭期间,有必要将所有内容写入磁盘。更常用的是局部检查点,局部检查点强制DBWn写入仅包含一个或多个数据文件(而不是整个数据库)的块的所有脏缓冲区:在数据文件或有表空间脱机时;在将表空间植入备份模式时;或在将表空间设置为只读时。与完全检查点相比,这些检查点的力度较小,每次在相关事件发生时自动执行。
Oracle切换日志文件时就会标记(建立)一个检查点。Oracle需要推进检查点,推进检查点后,就不再需要它刚填满的在线重做日志文件了。如果需要重用这个重做日志文件,而此时它还依赖于原来的重做日志文件,我们就会得到一个“检查点未完成”消息,而不惜等待。
可以看到,DBWn的性能可能很重要。如果它写出块的速度不够快,不能很快地释放缓冲区(可以重用来缓存其他块),就会看到Free Buffer Waits和Write Complete Waits的等待数和等待时间开始增长。
最好的情况下,DBWn使用异步I/O将块写至磁盘。采用异步I/O,DBWn会收集一批要写的块,并把它们交给操作系统。DBWn并不等待操作系统真正将块写出;而是立即返回,并收集下一批要写的块,当操作系统完成写操作时,它会异步地通知DBWn写操作已经完成。这样,与所有工作都串行进行相比,DBWn可以更快地工作。
关于DBWn,还有最后一点说明。根据定义,块写入器会把块写出到所有磁盘,即分散在各个磁盘上;也就是说,DBWn会做大量的分散写(scattered write)。执行一个更新时,你会修改多处存储的索引块,还可能修改随机地分布在磁盘上的数据块。另一方面,LGWR则是向重做日志完成大量的顺序写(sequential write)。这是一个很重要的区别,Oracle之所以不仅有一个重做日志和LGWR进程,还有DBWn进程,其原因就在于此。分散写比顺序写慢多了。通过在SGA中缓存脏块,并由LGWR进程完成大规模顺序写(可能重建这些脏缓冲区),这样可以提升性能。DBWn在后台完成它的任务(很慢),而LGWR在用户等待时完成自己的任务(这个任务比较快),这样我们就能得到更好的整体性能。尽管从技术上讲这样会使Oracle执行更多不必要的I/O(写日志以及写数据文件),但整体性能还是会提高。从理论上讲,如果提交期间Oracle已经将已修改的块物理地写出到磁盘,就可以跳过写在线重做日志文件。但实际中并不是这样:LGWR还是会把每个事务的重做信息写至在线重做日志,DBWn则在后台将数据库块刷新输出到磁盘。
LGWR
LGWR(log writer)将日志缓冲区的内容写入到磁盘上的联机日志文件中。将日志缓冲区写入联机重做日志文件的过程通常称为“日志缓冲区转储”。
当会话对数据库缓冲区缓存中的块执行任何更改时,在其将更改应用到块之前,会将要应用的变更向量写入磁盘。为此LGWR将日志缓冲区的内容几乎实时地传输到联机重做日志文件中。当会话发出COMMIT时,LGWR会实时写入:在LGWR将缓冲区写入磁盘时,会话将挂起。只有此时才将事务记录为已经提交(因此是不可逆的)。
在以下3种情况下,LGWR将转储日志缓冲区:DBWn要写入脏缓冲区;任何事务发出一个提交时;重做日志缓冲区1/3满。
提交时写入:为了处理COMMIT,服务器进程在日志缓冲区中插入提交记录。在LGWR将缓冲区写入磁盘时,会话将挂起。只有此写操作完成时,才能将提交完成的消息返回给会话,服务器进程才能继续工作。这将确保事务永不丢失:已提交事务的每个变更向量都可以在磁盘的重做日志上得到,并可以在伺候应用于数据文件备份。因此,如果数据库被破坏,那么可以通过备份进行还原,而且可以重做自备份以来执行的所有工作。
重做日志缓冲区的占用率达到1/3:此时,LGWR会将日志缓冲区转储到磁盘。这与性能相关。如果日志缓冲区较小(通常也应该这样),即使没有回话提交事务,占用率达到1/3的相应触发器将强制LGWR将缓冲区准实时写入磁盘。就大多数应用程序而言,日志缓冲区的优化大小仅为数MB。应用程序将在几分之一秒的时间内生成足以填充1/3的重做内容,因此会强制LGWR将变更向量不断地准实时写入磁盘。此后,当会话发出COMMIT命令时,几乎没有任何要写入的内容:COMMIT命令可以立即完成。
DBWn要将脏缓冲区从数据库缓冲区缓存写入到数据文件中:在执行此操作前,它会通知LGWR将日志缓冲区转储到联机重做日志文件中。这样做可以确保:始终可以反转未提交的事务。此处需要了解,DBWn完全可能将未提交的事务写入数据文件。只要一定能够获得反转事务所需的撤销数据,这就不成问题。在生成撤销数据时,也会生成变更向量。在更新数据文件前,这些已经在重做日志文件中,如有必要,可以重建回滚事务所需的撤销数据。注意,导致LGWR执行写入的三秒超时是存在的。超时实际上在DBWn上,但由于LGWR总是先于DBWn执行写入,LGWR上也就有了三秒钟的超时。
CKPT
检查点进程(Checkpoint Process)并不像它的名字所暗示的那样真的建立检查点,建立检查点主要是DBWn的任务。CKPT只是更新数据文件的文件首部,以辅助真正建立检查点的进程(DBWn)。当前检查点位置,是发生实例故障时重做流中必须由此开始的恢复位置。CKPT使用当前检查点位置不断更新控制文件。
MMON
MMON(manageability monitor)是数据库的很多自我监视和自我调整功能的支持进程。此数据库实例收集有关活动和性能的大量统计数据,这些统计数据收集到SGA中,通过发出SQL查询,可以查询它们的当前值。为了调整性能,也为了分析趋势和获得历史报告,有必要将这些统计数据保存到长期存储的地方。MMON从SGA定期捕获统计数据(默认是每小时一次),并将它们写入到数据字典中,可以无限期地存储它们(不过,默认方式是只存储8天)。MMON还持续监视数据库和实例,来确定是否应该发出任何警报。
MMNL
MMNL(manageability monitor light)是MMON的辅助进程。有时,MMON的预订活动显得不足。例如,MMON根据调度安排将SGA中收集的统计信息转储到数据库中:默认方式下是每小时一次。如果在MMON预定执行转储前,用于收集此信息的内存缓冲区变慢,那么,MMNL将担当起转储数据的职责。
MMAN
MMAN(memory manager)进程支持内存分配的自动管理。DBA仅需为内存使用情况确定一个总体目标,MMAN将观察PGA内存和SGA内存的需要,并根据需要将内存分配给会话和SGA结构,同时将内存分配总量保持在DBA设定的限制范围内。
LREG
数据库实例尝试用数据库侦听器注册它自己。这就允许用户通过侦听器连接数据库。在高级环境中,例如带有几个实例的群集数据库(提供了许多服务),LREG(listener regulation process)也会用工作负载和性能信息更新侦听器。这样侦听器就可以智能地与合适的实例进行会话。在早期版本中,这个功能由PMON进程实现。在12c版本中,添加了一个专用的进程LREG来实现它。
ARCn
ARCn(archiver)进程的任务是:当LGWR将在线重做日志文件填满时,就将其复制到另一个位置。此后这些归档的重做日志文件可以用于完成介质恢复。在线重做日志用于在出线电源故障(实例中止)时“修正”数据文件,而归档重做日志则不同,它是在出线硬盘故障时用于“修正”数据文件。如果丢失了包含数据文件/d01/oradata/ora11g/system.dbf的磁盘,可以去找上一周的备份,恢复旧的文件副本,并要求在数据库上应用自这次备份之后生成的所有归档和在线重做日志。这样就能使这个数据文件“赶上”数据库中的其他数据文件,所以我们可以继续处理而不会丢失数据。
ARCn通常将在线重做日志文件复制到至少两个位置。这些位置可能是本地机器上的磁盘,或者更确切地将,至少有一个位置在另一台机器上,以应付灾难性的失败。在许多情况下,归档重做日志文件会由另外某个进程复制到一个第三辅存设备上,如磁带。也可以将这些归档重做日志文件发送到另一台机器上,应用于“备用数据库”(standby database),这是Oracle提供的一个故障转移选项。
RECO
RECO(recoverer process)分布式数据库恢复有一个很中心的任务:由于两段提交(two-phase commit,2PC)期间的崩溃或链接丢失等原因,有些事务可能会保持准备状态,这个进程就是要恢复这些事务。2PC是一种分布式协议,允许影响多个不同数据库的修改实现原子提交。它力图在提交之前尽可能地关闭分布式失败窗口。如果在N个数据库中间采用2PC,其中一个数据(通常是客户最初登录的那个数据库,但也不一定)将成为协调器(coodinator)。这个站点会询问其他N-1个站点是否准备提交。实际上,这个站点会转向另外这N-1个站点,问它们是否准备好提交。这N-1个站点都会返回其“准备就绪状态”,报告为YES或NO。如果任何一个站点投票(报告)NO,整个事务都要回滚。如果所有站点都投票YES,站点协调器就会广播一条消息,使这N-1个站点真正完成提交(提交得到持久地存储)。
如果某个站点邮票YES,称其准备好要提交,但是在此之后,并且在得到协调器的指令真正提交之前,网络失败了,或者出现了另外某个错误,事务就会成为一个可疑的分布式事务(in_doubt distributed transaction)。2PC力图限制出现这种情况的时间窗口,但是无法根除这种情况。如果正好在那时(这个时间窗口内)出现一个失败,处理事务的工作就要由RECO负责。RECO会试图联系事务的协调器来发现协调的结果。在此之前,事务会保持未提交状态。当再次到达事务协调器时,RECO可能会提交事务,也可能将事务回滚。
需要说明,如果失败(outrage)持续很长一段时间,而且你有一些很重要的事务,可以自行手动地提交或回滚。有事你可能想要这样做,因为可疑的分布式事务科能导致写入器阻塞读取器(Oracle中只有此时会发生“写阻塞读”的情况)。你的DBA可以通知另一个数据库的DBA,要求他查询那些可疑事务的状态。然后你的DBA再提交或回滚,而不再由RECO完成这个任务。