用户进程与服务器进程
进程在Windows平台上通常可以看作一个可执行的程序或者是服务,可以通过Windows操作系统的任务管理器查看当前操作系统上运行的进程;在Linux系统中,可以使用 ps -ef 命令来查看当前活动的进程。这些进程有的是后台进程,随实例启动,有的是服务器进程,每当有会话连入Oracle数据块时,就会开始一个服务器进程。对于专用服务器连接来说,一个用户会有一个专门的服务器进程,而对于共享服务器来说,则只会具有一个或多个调度器进程。
在Oracle中,进程可以理解为如下几类:
- 用户进程:一般指客户端上运行的Oracle应用程序或工具创建的进程;
- 服务器进程:当客户端向服务器端发送操作请求时,Oracle会创建一个相应的服务器进程,它代表客户会话完成工作的进程,应用程序向数据库发送的SQL语句最后就要由这些进程接收并执行;
- 后台进程:这些进程随数据库而启动,用于完成各种维护任务,比如数据库写入进程 DBWn 、日志写入进程 LGWR 、检查点进程 CKPT 等,都属于后台进程。用户可以通过 v$bgprocess 查询关于后台进程的信息;
- 从属进程:用于为后台进程或服务器进程提供额外的执行任务。
进程的结构取决于操作系统及数据库配置为专用服务器还是共享服务器连接,在共享服务器体系结构中,一个运行数据库代码的服务器进程可能为多个客户端提供服务,Oracle实例与进程间的组成结构如图所示,这个图也可以看作时整个Oracle数据库的体系结构图。
用户进程可能位于网络上的其他位置,它们通过 Oracle Net 与Oracle服务器进程通信,每当一个用户进程连接到Oracle,Oracle就会产生一个相应的服务器进程,只有实例的服务器进程才能够访问SGA,比如使用 SQL*Plus连接到Oracle,在Oracle服务器上使用 ps -ef 命令可以查询到一个使用相应的服务器进程。
注意:数据库连接与数据库会话是两个不同的概念,连接是用户进程与Oracle实例间的通信通道,会话是用户通过用户进程与Oracle实例建立的连接,比如启动 SQL*Plus并输入用户名密码后,就与Oracle实例建立了一个会话。
Oracle数据库根据用户进程的连接来创建服务器进程,以处理连接到实例的客户端进程的请求。服务器进程可以执行一个或多个下列任务:
- 解析并运行通过应用程序发出的SQL语句,包括创建和执行查询计划;
- 执行PL/SQL代码;
- 将数据块从数据文件读入数据库缓冲区高速缓存,已经修改的块写回磁盘属于DBWn后台进程写入;
- 返回执行结果信息,以便应用程序可以进一步处理。
Oracle数据库的专用服务器连接时, 客户端连接与一个且仅与一个服务器进程连接,而共享服务器连接中,客户端连接不是直接与服务器进程进行连接的,它会被连接到一个调度进程上。Oracle默认使用专用服务器连接创建数据库,DBCA也提供了共享服务器选项。
PMON与SMON进程
在Oracle中,几个主要的后台进程如下:
- 数据块写入器进程 DBWn,将更改的数据从缓冲区高速缓存写入磁盘上的数据文件中。
- 日志写入器进程LGWR,将重做日志缓冲区中的内容写入到联机重做日志文件。
- 检查点进程 CKPT ,更新所有数据文件的头以记录检查点的详细信息。
- 进程监控进程 PMON,清除完成后的进程和失败的进程。
- 系统监控进程 SMON,执行崩溃恢复并合并区。
- 归档进程 ARCn,归档填满的联机重做日志文件。
- 可管理监控进程 MMON,执行数据库可管理相关的任务。
- 可管理监控器灯 MMNL,执行诸如捕捉会话历史和度量标准的任务。
- 内存管理进程 MMAN,调整SGA部件的大小。
- 作业队列调整进程 CJQO,调整作业队列以加速作业进程。
除了上面所列的进程之外,还有一些进程在使用Oracle的高级功能时会出现,Oracle数据库后台进程也并不是在每种数据库配置中都存在。
PMON进程监视器:
PMON的全称是 Process Monitor ,称为进程监视器,它负责在异常中止的连接之后完成清理并释放资源。
PMON进程会监视其他的后台进程,当某个服务器进程或调度进程异常终止时,这个进程将负责清理数据库缓冲区高速缓存,释放客户端进程之前还在用的资源。比如PMON会回滚用户未提交的工作,如果用户进程在持有某些表锁时死机了,PMON会释放这些锁。并且PMON还会重新启动失败的服务器进程,并释放为失败的进程分配的SGA资源。
PMON就好像时一个进程清道夫,它的工作就是在服务器进程出现问题时做出清洁工作,多数情况下PMON并不会工作,它会定期地检查是否有中断的进程。
PMON进程会自动执行动态的服务登记,比如当一个新的数据库实例被创建之后,PMON进程用监听器登记该实例的信息。也就是说PMON会向Oracle TNS 监听器注册新实例,实例启动时,PMON进程询问公认的端口地址来查看是否启动并运行了一个监听器。
SMON系统监视器
如果说PMON只是一个进程清道夫的话,那么SMON可以看作是一个系统清道夫。SMON会负责各种系统级的清理工作,SMON的主要职责如下:
- 在实例启动时,如果有必要,SMON会执行实例恢复,如果在Oracle RAC 环境中,一个数据库实例的SMON进程可以为另一个失败的实例执行实例恢复工作;
- 在实例恢复过程中,由于读文件或表空间脱机错误而跳过的已经终止事务,由SMON进行恢复,当表空间或文件重新联机时,SMON会恢复该事务;
- 清除未使用的临时段,虽然临时表空间会自动完成空间的回收,但是有时候也需要使用SMON来清除临时表空间的内容,比如执行一个 create index 命令时,会话突然中止了。此时需要由SMON来清除临时表空间,其他操作创建的临时段也需要由SMON来负责管理。
- 合并空闲空间:在使用字典管理表空间时,SMON要获取表空间中相互连续的空闲区段,并把它们合并为一个更大的空闲空间。
- 收缩回滚段:如果设置收缩回滚段,SMON会自动将回滚段收缩为所设置的最佳大小。
和PMON一样,SMON也是一个按需启动的过程,该进程大多数时间处于非活动状态,只在需要时启动。
DBWn 与 LGWR 进程
Oracle对所有数据的修改都是在内存中完成的,由DBWn数据写入器进程定期的将脏数据(已经发生过更改的数据)从数据库缓冲区高速缓存中写入到实际的数据库文件中。数据库写入进程与事务提交 COMMIT 实际上是异步的,事务提交时,只是触发了 LGWR 日志写进程将重做日志高速缓存中的重做日志项写入到当前联机的重做日志文件中,这样即便发生了系统崩溃,也可以通过应用重做日志文件来进行介质恢复。
数据库写入器进程 DBWn
DBWn 后面的 n 表示的是数据库写入器进程的编号,第一个为 0 ,例如 DBW0 ,对于多数系统来说一个写入器已经足够,但是如果系统要修改的数据量巨大,可能需要配置额外的写入器进程,比如可以从 DBW1 配置到 DBW9 或和 DBWa 到 DBWj 来提高写入的性能。
可以使用Oracle初始化参数中的 db_writer_processes 来配置数据库写入器进程的个数,默认情况下,Oracle将根据服务器的CPU和处理器组的数量来分配数据库写入器进程的数量。例如在32个处理器的 HP-UX 服务器上,默认为4个数据库写入器进程,即每8个处理器一个数据库写入进程。所以对于单个处理器来说,设置额外的数据库写入器进程的意义不大。
DBWn的任务主要是监控数据库缓冲区高速缓存的使用,如果缓冲区的可用空间下降,则DBWn会把缓冲区中的某些数据写入到磁盘文件中,使得缓冲区中具有可用的内存容纳新的请求。数据库写入器进程使用了最近最少使用 LRU 算法,该算法根据数据自请求以来在缓冲区中停留的时间长度来保留数据,如果一块数据最近刚被请求过,则很有可能仍驻留在内存中。
DBWn 进程在以下条件下直接将脏数据写入到数据文件中
- 当数据库发布一个检查点时,比如可以使用 ALTER SYSTEM CHECKPOINT 强制发布一个检查点,将导致 DBWn 将脏数据写入到磁盘中。
- 当服务器进程在检查了缓冲区后仍然还找不到一个可用的缓冲区时会执行写入操作
- 每隔3秒钟会执行写入操作
DBWn 会尽可能用异步方式将脏缓冲区写放到磁盘,以便同时执行其他的处理。DBWn通过周期性的写出缓冲区中的内容,并推进检查点,以便在恢复数据库数据时可以从检查点位置开始进行恢复。DBWn以一种分散写的方式写入到数据文件,因为修改的数据块可能存储在多个不同的位置或不同的磁盘,这会导致DBWn的写入速度比较慢,LGWR则采用顺序写的方式,会拥有较好的性能。
日志写进程 LGWR
日志写进程会将重做日志缓冲区中的重做日志项写入到联机重做日志文件中,LGWR进程会写入自上次写入重做日志文件之后写入缓存区中的所有日志项。
LGWR 进程会在如下的条件出现时执行写入操作:
- 用户提交了一个事务
- 发生了在线重做日志切换
- 自 LGWR 最后一次写入到现在超过了3秒钟
- 重做日志缓冲区已达到 1/3 满,或包含了1MB以上被缓冲的数据
- DBWn 必须将修改的缓冲区写入到磁盘
在DBWn 可以将脏缓冲区写到磁盘之前,该缓冲区更改的记录必须被写入到磁盘,也就是说必须要将所做的更改事项写到重做日志文件中,因为 DBWn 的写入操作总是比LGWR 的写入操作要慢,因此先行将操作记录写入到重做日志文件中,即便 DBWn 写入出现失败,也不会导致数据丢失,因为还可以使用重做日志记录进行介质恢复。DBWn 在发现了一些重做记录未写入时,会通知 LGWR 将记录写入磁盘,直到LGWR写入完成 DBWn 才会开始数据库块的写入工作。
LGWR 可以同时写入重做日志组中的多个重做日志文件。一般建议将重做日志文件规划成多路复用的重做日志文件,以便于保留冗余的重做日志文件的副本,从而避免了单点故障带来的损失。如果组中的一个或多个日志成员损坏,LGWR将仅写到组中可用的成员中。如果重做日志组中没有一个成员可以写入重做日志项,LGWR 会发出错误的提示。
当向数据库发送一条 COMMIT 语句提交事务时,LGWR首先在重做日志缓冲区中放置一个提交记录,接下来将此纪录与提交事务有关的重做项立即写到重做日志。事务的提交记录写到重做日志是标志事务提交的关键条件,LGWR 会将事务分配的 SCN(系统更改号)写入到重做日志中,以便于在进行介质恢复时可以利用SCN,LGWR将重做日志写入后,将返回一个成功提交事务的提示。在DBWn 将更改的数据实际写入到磁盘之前指示成功提交的技术称为快速提交机制。
CKPT 与 ARCn 进程
CKPT检查点进程负责同志数据库写入器 DBWn 进程核实将内存缓冲区中的脏数据写入到磁盘,CKPT 进程并不像其名所暗示的那样真正建立检查点,真正建立检查点是 DBWn 的任务, CKPT 只是更新数据文件的文件头以辅助真正建立检查点的DBWn进程。检查点信息包含检查点位置、SCN、联机重做日志中的起始恢复位置等。CKPT 与 DBWn 的结构示意如图
可以看到,CKPT进程会更新控制文件及数据文件头和数据文件体中的检查点位置、SCN、联机重做日志中的起始恢复位置等信息。总而言之,检查点的目的就是为了同步缓冲区高速缓存的信息与数据库磁盘上的信息,每个检查点记录都由所有活动事务的列表和这些事务的最近日志记录的地址组成。检查点进程一般包括如下几个步骤:
- 把重做日志缓冲区中的内容刷新到重做日志文件
- 把检查点记录写入重做日志文件
- 把数据库缓冲区高速缓存的内容刷新到磁盘
- 在检查点完成任务后,更新数据文件头和控制文件
检查点由于维持了同步信息,因此其操作的频率直接关系到数据库崩溃后的恢复时间。
当数据库以归档模式运行时,归档日志进程 ARCn 会将联机重做日志文件复制到脱机存储位置,这些进程可能会手机事务重做数据,并将其传送到备用数据库目标位置。
只有在数据库运行在归档模式下,即 ARCHIVELOG 模式下,且自动归档功能被开启时,系统才会启动 ARCn 进程执行归档操作。在一个Oracle实例中,最多可以运行 10 个 ARCn 进程,分别是(ARC0 到 ARC9),LGWR 会在当前的进程不能满足工作负荷时自动启用新的 ARCn 进程。当 LGWR 启动新的 ARCn 进程时,也会在警告日志中记录数据。
可以通过初始化参数 log_archive_max_processes 来设置多个归档日志进程,比如可以使用下面的语句将归档日志设置为 10 个进程:
alter system set log_archive_max_processes=10 SCOPTE=BOTH;
实际上由于系统能够自动决定需要多少个 ARCn 进程,一般很少手动的修改归档日志进程数。