Oracle数据库进程

       Oracle中的各个进程要完成某个特定的任务或一组任务,每个进程都会分配内部内存(PGA 内存)来完成它的任务。Oracle实例主要有3 类进程:

       (1)服务器进程(serverprocess):这些进程根据客户的请求来完成工作。我们已经对专用服务器和共享服务器有了一定的了解。它们就是服务器进程。

       (2)后台进程(backgroundprocess):这些进程随数据库而启动,用于完成各种维护任务,如将块写至磁盘、维护在线重做日志、清理异常中止的进程等。

       (3)从属进程(slaveprocess):这些进程类似于后台进程,不过它们要代表后台进程或服务器进程完成一些额外的工作。


       在某些操作系统(如Windows)上,Oracle使用线程实现,所以在这种操作系统上,就要把我们所说的“进程”理解为“线程”的同义词。

        “进程”一词既表示进程,也涵盖线程。如果你使用的是一个多进程的Oracle 实现,比如说UNIX 上的Oracle 实现,“进程”就很贴切。如果你使用的是单进程的Oracle 实现,如Windows上的Oracle 实现,“进程”实际是指“Oracle 进程中的线程”。所以,举例来说,当我谈到DBWn 进程时,在Windows 上就对应为Oracle 进程中的DBWn 线程


一. 服务器进程


关于服务进程的分类,之前有整理过一篇文章:

       OracleDedicated server 和Shared server(专用模式 和 共享模式) 说明


       服务器进程就是代表客户会话完成工作的进程。应用向数据库发送的SQL 语句最后就要由这些进程接收并执行。

       (1)专用服务器(dedicatedserver)连接,采用专用服务器连接时,会在服务器上得到针对这个连接的一个专用进程。数据库连接与服务器上的一个进程或线程之间存在一对一的映射。

       (2)共享服务器(sharedserver)连接,采用共享服务器连接时,多个会话可以共享一个服务器进程池, 其中的进程由Oracle 实例生成和管理。你所连接的是一个数据库调度器(dispatcher),而不是特意为连接创建的一个专用服务器进程。


注意连接和会话之间的区别:

       (1)连接(connection)就是客户进程与Oracle 实例之间的一条物理路径(例如,客户与实例之间的一个网络连接)。

       (2)会话(session)则不同,这是数据库中的一个逻辑实体,客户进程可以在会话上执行SQL 等。多个独立的会话可以与一个连接相关联,这些会话甚至可以独立于连接存在。


       专用服务器进程和共享服务器进程的任务是一样的:要处理你提交的所有SQL。当你向数据库提交一个SELECT * FROM EMP 查询时,会有一个Oracle 专用/共享服务器进程解析这个查询,并把它放在共享池中(或者最好能发现这个查询已经在共享池中)。这个进程要提出执行计划,如果必要,还要执行这个执行计划,可能在缓冲区缓存中找到必要的数据,或者将数据从磁盘读入缓冲区缓存中。这些服务器进程是干重活的进程。在很多情况下,你都会发现这些进程占用的系统CPU 时间最多,因为正是这些进程来执行排序、汇总、联结等等工作,几乎所有工作都是这些进程做的。


1.1 专用服务器连接

       在专用服务器模式下,客户连接和服务器进程(或者有可能是线程)之间会有一个一对一的映射。如果一台UNIX 主机上有100 条专用服务器连接,就会有相应的100 个进程在执行。可以用图来说明,如图5-1 所示。

      ​​


        客户应用中链接着Oracle 库,这些库提供了与数据库通信所需的API。这些API 知道如何向数据库提交查询,并处理返回的游标。它们知道如何把你的请求打包为网络调用,专用服务器则知道如何将这些网络调用解开。这部分软件称为Oracle Net,不过在以前的版本中可能称之为SQL*Net 或Net8。这是一个网络软件/协议,Oracle 利用这个软件来支持客户/服务器处理(即使在一个n 层体系结构中也会“潜伏”着客户/服务器程序)。不过,即使从技术上讲没有涉及Oracle Net,Oracle 也采用了同样的体系结构。也就是说,即使客户和服务器在同一台机器上,也会采用这种两进程(也称为两任务)体系结构。


这个体系结构有两个好处:

       (1)远程执行(remoteexecution):客户应用可能在另一台机器上执行(而不是数据库所在的机器),这是很自然的。

       (2)地址空间隔离(addressspace isolation):服务器进程可以读写SGA。如果客户进程和服务器进程物理地链接在一起,客户进程中一个错误的指针就能轻松地破坏SGA 中的数据结构。


1.2 共享服务器连接

       共享服务器连接强制要求必须使用Oracle Net,即使客户和服务器都在同一台机器上也不例外。如果不使用OracleTNS 监听器,就无法使用共享服务器。如前所述,客户应用会连接到Oracle TNS 监听器,并重定向或转交给一个调度器。调度器充当客户应用和共享服务器进程之间的“导管”。图5-2 显示了与数据库建立共享服务器连接时的体系结构。


 ​​

       在此可以看到,客户应用(其中链接了Oracle 库)会与一个调度器进程物理连接。对于给定的实例,可以配置多个调度器,但是对应数百个(甚至数千个)用户只有一个调度器的情况并不鲜见。调度器只负责从客户应用接收入站请求,并把它们放入SGA 中的一个请求队列。第一个可用的共享服务器进程(与专用服务器进程实质上一样)从队列中选择请求,并附加相关会话的UGA(图5-2 中标有“S”的方框)。共享服务器处理这个请求,把得到的输出放在响应队列中。调度器一直监视着响应队列来得到结果,并把结果传回给客户应用。就客户而言,它分不清到底是通过一条专用服务器连接还是通过一条共享服务器连接进行连接,看上去二者都一样,只是在数据库级二者的区别才会明显。


1.3 连接与会话

       在一条连接上可以建立0 个、一个或多个会话。各个会话是单独而且独立的,即使它们共享同一条数据库物理连接也是如此。一个会话中的提交不会影响该连接上的任何其他会话。实际上,一条连接上的各个会话可以使用不同的用户身份。


       在Oracle 中,连接只是客户进程和数据库实例之间的一条特殊线路,最常见的就是网络连接。这条连接可能连接到一个专用服务器进程,也可能连接到调度器。如前所述,连接上可以有0 个或多个会话,这说明可以有连接而无相应的会话。另外,一个会话可以有连接也可以没有连接。使用高级Oracle Net 特性(如连接池)时,客户可以删除一条物理连接,而会话依然保留(但是会话会空闲)。客户在这个会话上执行某个操作时,它会重新建立物理连接。


       连接(connection):连接是从客户到Oracle 实例的一条物理路径。连接可以在网络上建立,或者通过IPC 机制建立。通常会在客户进程与一个专用服务器或一个调度器之间建立连接。不过,如果使用Oracle 的连接管理器(Connection Manager ,CMAN),还可以在客户和CMAN之间以及CMAN 和数据库之间建立连接。

       会话(session):会话是实例中存在的一个逻辑实体。这就是你的会话状态(session state),也就是表示特定会话的一组内存中的数据结构。提到“数据库连接”时,大多数人首先想到的就是“会话”。你要在服务器中的会话上执行SQL、提交事务和运行存储过程。可以使用SQL*Plus 来看一看实际的连接和会话是什么样子,从中还可以了解到,实际上一条连接有多个会话的情况相当常见。


       这里使用了AUTOTRACE 命令,并发现有两个会话。我们在一条连接上使用一个进程创建了两个会话。以下是其中的第一个会话:

SQL> select username, sid, serial#, server,paddr, status from v$session where username='SYS';

USERNAME SID SERIAL# SERVER PADDR STATUS
------------------------------ -------------------- --------- -------- --------
SYS 153 27 DEDICATED 3621B264 ACTIVE


以上PADDR 列是这个专用服务器进程的地址。


下面,只需打开AUTOTRACE来查看SQL*Plus 中所执行语句的统计结果:

SQL> set autotrace on statistics
SQL> select username, sid, serial#,server, paddr, status from v$session where username='SYS';

USERNAME SID SERIAL# SERVER PADDR STATUS
------------------------------ -------------------- --------- -------- --------
SYS 152 88 DEDICATED 3621B264 INACTIVE
SYS 153 27 DEDICATED 3621B264 ACTIVE


Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
770 bytes sent via SQL*Net toclient
385 bytes received via SQL*Netfrom client
2 SQL*Net roundtrips to/fromclient
0 sorts (memory)
0 sorts (disk)
2 rows processed


       此时有了两个会话,但是这两个会话都使用同一个专用服务器进程,从它们都有同样的PADDR 值就能看出这一点。从操作系统也可以得到确认,因为没有创建新的进程,对这两个会话只使用了一个进程(一条连接)。

       需要注意,其中一个会话(原来的会话)是ACTIVE(活动的)。这是有道理的: 它正在运行查询来显示这个信息,所以它当然是活动的。但是那个INACTIVE(不活动的)会话呢?那个会话要做什么?这就是AUTOTRACE 会话,它的任务是“监视”我们的实际会话,并报告它做了什么。


       在SQL*Plus 中启用(打开)AUTOTRACE 时,如果我们执行DML 操作(INSERT、UPDATE、DELETE、SELECT和MERGE),SQL*Plus 会完成以下动作:

       (1)如果还不存在辅助会话[1],它会使用当前连接创建一个新会话。

       (2)要求这个新会话查询V$SESSTAT视图来记住实际会话(即运行DML的会话)的初始统计值。

       (3)在原会话中运行DML 操作。

       (4)DML 语句执行结束后,SQL*Plus会请求另外那个会话(即“监视”会话)再次查询V$SESSTAT,并生成前面所示的报告,显示出原会话(执行DML 的会话)的统计结果之差。


       如果关闭AUTOTRACE,SQL*Plus 会终止这个额外的会话,在V$SESSION 中将无法看到这个会话。你可能会问:“SQL*Plus 为什么要这样做,为什么要另建一个额外的会话?”。原因是:如果使用同一个会话来监视内存使用,那执行监视本身也要使用内存。

       如果在同一个会话中观察统计结果,就会对统计结果造成影响(导致对统计结果的修改)。倘若SQL*Plus使用一个会话来报告所执行的I/O 次数,网络上传输了多少字节,以及执行了多少次排序,那么查看这些详细信息的查询本身也会影响统计结果。这些查询可能自己也要排序、执行I/O 以及在网络上传输数据等(一般来说都会如此!)。因此,我们需要使用另一个会话来正确地测量。


       到目前为止,我们已经看到一条连接可以有一个或两个会话。现在,我们想使用SQL*Plus 来查看一条没有任何会话的连接。这很容易。在上例所用的同一个SQL*Plus 窗口中,只需键入一个“很容易误解”的命令即DISCONNECT:


ops$tkyte@ORA10G> set autotrace off

ops$tkyte@ORA10G> disconnect


       从技术上讲,这个命令应该叫DESTROY_ALL_SESSIONS 更合适,而不是DISCONNECT,因为我们并没有真正物理地断开连接。

       注意在SQL*Plus 中要真正地断开连接,应该执行“exit”命令,因为你必须退出才能完全撤销连接。不过,我们已经关闭了所有会话。


使用另一个用户账户打开另一个会话,并查询原用户SYS。

SQL> select username, sid, serial#,server, paddr, status from v$session where username='SYS';

no rows selected


       可以看到,这个账户名下没有会话,但是仍有一个进程,相应地有一条物理连接(使用前面的ADDR值):


SQL> select username, program fromv$process where addr = hextoraw('3621B264');


USERNAME        PROGRAM

---------------------------------------------------------------

oracle          oracle@db1 (TNS V1-V3)


       所以,这就有了一条没有相关会话的“连接”。可以使用SQL*Plus 的CONNECT 命令(这个命令的名字也起得不恰当),在这个现有的进程中创建一个新会话(CONNECT命令叫CREATE_SESSION更合适):


SQL> conn / as sysdba;
Connected.
SQL> select username, sid, serial#,server, paddr, status from v$session where username='SYS';

USERNAME SID SERIAL# SERVER PADDR STATUS
------------------------------ -------------------- --------- -------- --------
SYS 158 34 DEDICATED 3621B264 ACTIVE

       可以注意到,PADDR 还是一样的,所以我们还是在使用同一条物理连接,但是(可能)有一个不同的SID。我说“可能有”,是因为也许还会分配同样的SID,这取决于在我们注销时是否有别人登录,以及我们原来的SID 是否可用。

到此为止,这些测试都是用一条专用服务器连接执行的,所以PADDR 正是专用服务器进程的进程地址。



二. 后台进程

       Oracle实例包括两部分:SGA 和一组后台进程。后台进程执行保证数据库运行所需的实际维护任务。

       例如,有一个进程为我们维护块缓冲区缓存,根据需要将块写出到数据文件。另一个进程负责当在线重做日志文件写满时将它复制到一个归档目标。另外还有一个进程负责在异常中止进程后完成清理,等等。每个进程都专注于自己的任务,但是会与所有其他进程协同工作。例如,负责写日志文件的进程填满一个日志后转向下一个日志时,它会通知负责对填满的日志文件进行归档的进程,告诉它有活干了。

       可以使用一个V$视图查看所有可能的Oracle 后台进程,确定你的系统中正在使用哪些后台进程:


SQL> select paddr, name, descriptionfrom v$bgprocess order by paddr desc;

PADDR NAME DESCRIPTION
-------- ---------------------------------------------------------------------
3621D49C QMNC AQ Coordinator
3621CEE8 ARC2 Archival Process 2
3621C934 ARC1 Archival Process 1
3621C380 ARC0 Archival Process 0
3621A148 MMNL Manageability Monitor Process 2
36219B94 MMON Manageability Monitor Process
362195E0 CJQ0 Job Queue Coordinator
3621902C RECO distributed recovery
36218A78 SMON System Monitor Process
362184C4 CKPT checkpoint
36217F10 LGWR Redo etc.

PADDR NAME DESCRIPTION
-------- ---------------------------------------------------------------------
3621795C DBW0 db writer process 0
362173A8 MMAN Memory Manager
36216DF4 PSP0 process spawner 0
36216840 PMON process cleanup
00 DIAG diagnosibility process
00 FMON File Mapping Monitor Process
00 LMON global enqueue servicemonitor
00 LMD0 global enqueue servicedaemon 0
.....
00 ASMB ASM Background
00 GMON diskgroup monitor

157 rows selected.


注意:这个视图中PADDR 不是00 的行都是系统上配置和运行的进程(线程)。


       有两类后台进程:有一个中心(focused)任务的进程(如前所述)和完成各种其他任务的进程(即工具进程)。


例如,内部作业队列( jobqueue)有一个工具后台进程,可以通过DBMS_JOB 包使用它。这个进程会监视作业队列,并运行其中的作业。在很多方面,这就像一个专用服务器进程,但是没有客户连接。

下面会分析各种后台进程,先来看有中心任务的进程,然后再介绍工具进程。


2.1 中心后台进程

图5-4 展示了有一个中心(focused)用途的Oracle 后台进程。



       启动实例时也许不会看到所有这些进程,但是其中一些主要的进程肯定存在。如果在ARCHIVELOG 模式下,你可能只会看到ARCn(归档进程),并启用自动归档。如果运行了Oracle RAC,这种Oracle 配置允许一个集群中不同机器上的多个实例装载并打开相同的物理数据库,就只会看到LMD0、LCKn、LMON 和LMSn。


       意为简洁起见,图5-4 中没有画出共享服务器调度器(Dnnn)和共享服务器(Snnn)进程。因此,图5-4 大致展示了启动Oracle 实例并装载和打开一个数据库时可能看到哪些进程。例如,在我的Linux 系统上,启动实例后,有以下进程:

[oracle@db1 ~]$ ps -ef|grep 'ora_.*_dave*'
oracle 4123 1 0 20:13 ? 00:00:05 ora_pmon_dave1
oracle 4125 1 0 20:13 ? 00:00:05 ora_psp0_dave1
oracle 4127 1 0 20:13 ? 00:00:02 ora_mman_dave1
oracle 4129 1 0 20:13 ? 00:00:05 ora_dbw0_dave1
oracle 4131 1 0 20:13 ? 00:00:21 ora_lgwr_dave1
oracle 4133 1 0 20:13 ? 00:00:13 ora_ckpt_dave1
oracle 4135 1 1 20:13 ? 00:01:12 ora_smon_dave1
oracle 4137 1 0 20:13 ? 00:00:04 ora_reco_dave1
oracle 4139 1 0 20:13 ? 00:00:16 ora_cjq0_dave1
oracle 4141 1 1 20:13 ? 00:01:33 ora_mmon_dave1
oracle 4143 1 0 20:13 ? 00:00:08 ora_mmnl_dave1
oracle 4145 1 0 20:13 ? 00:00:00 ora_d000_dave1
oracle 4147 1 0 20:13 ? 00:00:00 ora_s000_dave1
oracle 4156 1 0 20:13 ? 00:00:01 ora_arc0_dave1
oracle 4158 1 0 20:13 ? 00:00:05 ora_arc1_dave1
oracle 4163 1 0 20:14 ? 00:00:03 ora_qmnc_dave1
oracle 4167 1 0 20:15 ? 00:00:24 ora_q000_dave1
oracle 4169 1 020:15 ? 00:00:00 ora_q001_dave1
oracle 5109 1 1 21:48 ? 00:00:00 ora_j000_dave1
oracle 5141 5111 0 21:49 pts/4 00:00:00 grep ora_.*_dave2*


       这些进程命名规则:进程名都以ora_开头。后面是4 个字符,表示进程的具体名字,再后面是ORACLE_SID,(站点标识符)。


       在UNIX 上,可以很容易地标识出Oracle后台进程,并将其与一个特定的实例关联(在Windows 上则没有这么容易,因为在Windows 上这些后台进程实际上只是一个更大进程中的线程)。

       这些进程实际上都是同一个二进制可执行程序,对于每个“程序”,并没有一个单独的可执行文件。你可以尽可能地查找一下,但是不论在磁盘的哪个位置上肯定都找不到一个arc0 二进制可执行程序,同样也找不到LGWR或DBW0。这些进程实际上都是oracle(也就是所运行的二进制可执行程序的名字)。它们只是在启动时对自己建立别名,以便更容易地标识各个进程。这样就能在UNIX 平台上高效地共享大量对象代码。Windows上就没有什么特别的了,因为它们只是进程中的线程,因此,当然只是一个大的二进制文件。


对于几个主要的后台进程,在下面的blog 有说明:

       ​​Oracle 后台进程 说明​


这里补充几个里面没有提到的进程说明:

       自动存储管理后台(Automatic Storage Management Background,ASMB)进程:ASMB 进程在使用了ASM 的数据库实例中运行。它负责与管理存储的ASM 实例通信、向ASM 实例提供更新的统计信息,并向ASM 实例提供一个“心跳”,让ASM 实例知道它还活着,而且仍在运行。

       重新平衡(Rebalance,RBAL)进程:RBAL 进程也在使用了ASM 的数据库实例中运行。向ASM磁盘组增加或去除磁盘时,RBAL 进程负责处理重新平衡请求(即重新分布负载的请求)。


以下进程出现在Oracle RAC 实例中。RAC 是一种Oracle 配置,即集群中的多个实例可以装载和打开一个数据库,其中每个实例在一个单独的节点上运行(通常节点是一个单独的物理计算机)。这样,你就能有多个实例访问(以一种全读写方式)同样的一组数据库文件。


RAC 的主要目标有两个:

       高度可用性:利用Oracle RAC,如果集群中的一个节点/计算机由于软件、硬件或人为错误而失败,其他节点可以继续工作,还可以通过其他节点访问数据库。你也许会丧失一些计算能力,但是不会因此而无法访问数据库。

       可扩缩性:无需购买更大的机器来处理越来越大的工作负载(这称为垂直扩缩),RAC 允许以另一种方式增加资源,即在集群中增加更多的机器(称为水平扩缩)。举例来说,不必把你的4 CPU 机器扩缩为有8 个或16 个CPU,通过利用RAC,你可以选择增加另外一个相对廉价的4 CPU机器(或多台这样的机器)。


以下进程是RAC 环境所特有的:

       锁监视器(Lockmonitor,LMON)进程:LMON 监视集群中的所有实例,检测是否有实例失败。这有利于恢复失败实例持有的全局锁。它还负责在实例离开或加入集群时重新配置锁和其他资源(实例失败时会离开集群,恢复为在线时又会加入集群,或者可能有新实例实时地增加到集群中)。

       锁管理器守护(Lockmanager daemon,LMD)进程:LMD 进程为全局缓存服务(保持块缓冲区在实例间一致)处理锁管理器服务请求。它主要作为代理(broker)向一个队列发出资源请求,这个队列由LMSn 进程处理。LMD 会处理全局死锁的检测/解析,并监视全局环境中的锁超时。

       锁管理器服务器(Lockmanager server,LMSn)进程:前面已经提到,在一个RAC 环境中,各个Oracle 实例在集群中的不同机器上运行,它们都以一种读写方式访问同样的一组数据库文件。为了达到这个目的,SGA 块缓冲区缓存相互之间必须保持一致。这也是LMSn 进程的主要目标之一。在以前版本的Oracle 并行服务器(Oracle Parallel Server,OPS)中,这是通过ping实现的。也就是说,如果集群中的一个节点需要块的一个读一致视图,而这个块以一种独占模式被另一个节点锁定,数据的交换就要通过磁盘刷新输出来完成(块被ping)。如果本来只是要读取数据,这个操作(ping)的代价就太昂贵了。现在则不同,利用LMSn,可以在集群的高速连接上通过非常快速的缓存到缓存交换来完成数据交换。每个实例可以有多达10 个LMSn 进程。

       锁(Lock,LCK0)进程:这个进程的功能与前面所述的LMD 进程非常相似,但是它处理所有全局资源的请求,而不只是数据库块缓冲区的请求。

       可诊断性守护(Diagnosabilitydaemon,DIAG)进程:DIAG 只能用于RAC 环境中。它负责监视实例的总体“健康情况”,并捕获处理实例失败时所需的信息。


2.2 工具后台进程

       这些后台进程全都是可选的,可以根据你的需要来选用。它们提供了一些工具,不过这些工具并不是每天运行数据库所必需的,除非你自己要使用(如作业队列),或者你要利用使用了这些工具的特性(如新增的Oracle 10g 诊断功能)。


       在UNIX 中,这些进程可以像其他后台进程一样可见,如果你执行ps 命令,就能看到这些进程。 

[oracle@db1 ~]$ ps -ef|grep 'ora_.*_dave*'
oracle 4123 1 0 20:13 ? 00:00:05 ora_pmon_dave1
oracle 4125 1 0 20:13 ? 00:00:05 ora_psp0_dave1
oracle 4127 1 0 20:13 ? 00:00:02 ora_mman_dave1
oracle 4129 1 0 20:13 ? 00:00:05 ora_dbw0_dave1
oracle 4131 1 0 20:13 ? 00:00:21 ora_lgwr_dave1
oracle 4133 1 0 20:13 ? 00:00:13 ora_ckpt_dave1
oracle 4135 1 1 20:13 ? 00:01:12 ora_smon_dave1
oracle 4137 1 0 20:13 ? 00:00:04 ora_reco_dave1
oracle 4139 1 0 20:13 ? 00:00:16 ora_cjq0_dave1
oracle 4141 1 1 20:13 ? 00:01:33 ora_mmon_dave1
oracle 4143 1 0 20:13 ? 00:00:08 ora_mmnl_dave1
oracle 4145 1 0 20:13 ? 00:00:00 ora_d000_dave1
oracle 4147 1 0 20:13 ? 00:00:00 ora_s000_dave1
oracle 4156 1 0 20:13 ? 00:00:01 ora_arc0_dave1
oracle 4158 1 0 20:13 ? 00:00:05 ora_arc1_dave1
oracle 4163 1 0 20:14 ? 00:00:03 ora_qmnc_dave1
oracle 4167 1 0 20:15 ? 00:00:24 ora_q000_dave1
oracle 4169 1 020:15 ? 00:00:00 ora_q001_dave1
oracle 5109 1 1 21:48 ? 00:00:00 ora_j000_dave1
oracle 5141 5111 0 21:49 pts/4 00:00:00 grep ora_.*_dave*


2.2.1 CJQ0 和Jnnn 进程:作业队列

       在第一个7.0 版本中,Oracle 通过一种称为快照(snapshot)的数据库对象来提供复制特性。作业队列就是刷新快照(或将快照置为当前快照)时使用的内部机制。

       作业队列进程监视一个作业表,这个作业表告诉它何时需要刷新系统中的各个快照。在Oracle 7.1中,Oracle 公司通过一个名为DBMS_JOB 的数据库包来提供这个功能。所以,原先7.0 中与快照相关的进程到了7.1及以后版本中变成了“作业队列”。后来,控制作业队列行为的参数(检查的频度,以及应该有

多少个队列进程)的名字也发生了变化,从SNAPSHOT_REFRESH_INTERVAL 和SNAPSHOT_REFRESH_PROCESSES变成了JOB_QUEUE_INTERVAL 和JOB_QUEUE_PROCESSES。在当前的版本中,只有JOB_QUEUE_PROCESSES 参数的设置是用户可调的。

       最多可以有1000 个作业队列进程。名字分别是J000,J001,…,J999。这些进程在复制中大量使用,并作为物化视图刷新进程的一部分。基于流的复制(Oracle9iRelease 2 中新增的特性)使用AQ 来完成复制,因此不使用作业队列进程。

       开发人员还经常使用作业队列来调度一次性(后台)作业或反复出现的作业,例如,在后台发送一封电子邮件,或者在后台完成一个长时间运行的批处理。通过在后台做这些工作,就能达到这样一种效果:尽管一个任务耗时很长,但在性急的最终用户看来所花费的时间并不多(他会认为任务运行得快多了,但事实上可能并非如此)。这与Oracle 用LGWR 和DBWn 进程所做的工作类似,他们在后台做大量工作,所以你不必实时地等待它们完成所有任务。


       Jnnn 进程与共享服务器很相似,但是也有专用服务器中的某些方面。它们处理完一个作业之后再处理下一个作业,从这个意义上讲是共享的,但是它们管理内存的方式更像是一个专用服务器(其UGA 内存在PGA 中,而不是在SGA 中)。每个作业队列进程一次只运行一个作业,一个接一个地运行,直至完成。正因为如此,如果我们想同时运行多个作业,就需要多个进程。这里不存在多线程或作业的抢占。一旦运行一个作业,就会一直运行到完成(或失败)。


       你会注意到,经过一段时间,Jnnn 进程会不断地来来去去,也就是说,如果配置了最多1 000 个Jnnn进程,并不会看到真的有1 000 个进程随数据库启动。相反,开始时只会启动一个进程,即作业队列协调器(CJQ0),它在作业队列表中看到需要运行的作业时,会启动Jnnn 进程。如果Jnnn 进程完成其工作,并发现没有要处理的新作业,此时Jnnn 进程就会退出,也就是说,会消失。因此,如果将大多数作业都调度为在凌晨2:00运行(没有人在场),你可能永远也看不到这些Jnnn 进程。


2.2.2 QMNC 和Qnnn:高级队列

       QMNC进程对于AQ 表来说就相当于CJQ0 进程之于作业表。QMNC 进程会监视高级队列,并警告从队列中删除等待消息的“出队进程”(dequeuer):已经有一个消息变为可用。QMNC和Qnnn 还要负责队列传播(propagation),也就是说,能够将在一个数据库中入队(增加)的消息移到另一个数据库的队列中,从而实现出队(dequeueing)。

       Qnnn 进程对于QMNC 进程就相当于Jnnn 进程与CJQ0 进程的关系。QMNC 进程要通知Qnnn 进程需要完成什么工作,Qnnn 进程则会处理这些工作。

       QMNC 和Qnnn 进程是可选的后台进程。参数AQ_TM_PROCESSES 可以指定最多创建10 个这样的进程(分别名为Q000,…,Q009),以及一个QMNC 进程。如果AQ_TM_PROCESSES 设置为0,就没有QMNC或Qnnn 进程。

       不同于作业队列所用的Jnnn进程,Qnnn 进程是持久的。如果将AQ_TM_PROCESSES 设置为10,数据库启动时可以看到10 个Qnnn 进程和一个QMNC 进程,而且在实例的整个生存期中这些进程都存在。


2.2.3 EMNn:事件监视器进程(Event Monitor Process)

       EMNn进程是AQ 体系结构的一部分,用于通知对某些消息感兴趣的队列订购者。通知会异步地完成。

       可以用一些Oracle 调用接口(Oracle Call Interface,OCI)函数来注册消息通知的回调。回调是OCI 程序中的一个函数,只要队列中有了订购者感兴趣的消息,就会自动地调用这个函数。EMNn 后台进程用于通知订购者, 第一次向实例发出通知时会自动启动EMNn 进程。然后应用可以发出一个显式的message_receive(dequeue)来获取消息。


2.2.4 MMAN:内存管理器(Memory Manager)

       这个进程是Oracle 10g 中新增的,自动设置SGA 大小特性会使用这个进程。MMAN 进程用于协调共享内存中各组件(默认缓冲区池、共享池、Java 池和大池)的大小设置和大小调整。


2.2.5 MMON、MMNL 和Mnnn:可管理性监视器(Manageability Monitor)

       这些进程用于填充自动工作负载存储库(Automatic WorkloadRepository,AWR),这是Oracle 10g中新增的一个特性。

       MMNL进程会根据调度从SGA 将统计结果刷新输出至数据库表。

       MMON进程用于“自动检测”数据库性能问题,并实现新增的自调整特性。     Mnnn 进程类似于作业队列的Jnnn 或Qnnn 进程;MMON 进程会请求这些从属进程代表它完成工作。Mnnn 进程本质上是临时性的,它们将根据需要来来去去。


2.2.6 CTWR:修改跟踪进程(Change Tracking Process)

       这是Oracle 10g 数据库中新增的一个可选进程。CTWR 进程负责维护新的修改跟踪文件。


2.2.7 RVWR:恢复写入器(Recovery Writer)

       这个进程也是Oracle 10g 数据库中新增的一个可选进程,负责维护闪回恢复区中块的“前”映像,要与FLASHBACKDATABASE 命令一起使用。


2.2.8 其他工具后台进程

       还有另外一些工具进程没有列出。例如,Oracle Data Guard 有一组与之相关的进程,有利于将重做信息从一个数据库移送到另一个数据库,并应用这些重做信息。还有一些进程与Oracle 10g 新增的数据泵工具有关,在某些数据泵操作中会看到这些进程。另外还有一些流申请和捕获进程。不过,以上所列已经基本涵盖了你可能遇到的大多数常用的后台进程。



三. 从属进程

       下面来看最后一类Oracle 进程:从属进程(slave process)。Oracle 中有两类从属进程:I/O 从属进程和并行查询从属进程。


3.1 I/O 从属进程

       I/O从属进程用于为不支持异步I/O的系统或设备模拟异步I/O。例如,磁带设备(相当慢)就不支持异步I/O。通过使用I/O 从属进程,可以让磁带机模仿通常只为磁盘驱动器提供的功能。就好像支持真正的异步I/O 一样,写设备的进程(调用者)会收集大量数据,并交由写入器写出。数据成功地写出时,写入器(此时写入器是I/O 从属进程,而不是操作系统)会通知原来的调用者,调用者则会从要写的数据列表中删除这批数据。

       采用这种方式,可以得到更高的吞吐量,这是因为会由I/O 从属进程来等待慢速的设备,而原来的调用进程得以脱身,可以做其他重要的工作来收集下一次要写的数据。

       I/O 从属进程在Oracle 中有两个用途。DBWn 和LGWR 可以利用I/O 从属进程来模拟异步I/O,另外RMAN写磁带时也可能利用I/O 从属进程。


有两个参数控制着I/O 从属进程的使用:

       BACKUP_TAPE_IO_SLAVES:这个参数指定RMAN 是否使用I/O 从属进程将数据备份、复制或恢复到磁带上。由于这个参数是围绕着磁带设备设计的,而且磁带设备一次只能由一个进程访问,所以这个参数是一个布尔值,而不是所用从属进程的个数(这可能出乎你的意料)。RMAN 会为所用的物理设备启动多个必要的从属进程。BACKUP_TAPE_IO_SLAVES = TRUE 时,则使用一个I/O 从属进程从磁带设备读写。如果这个参数为FALSE(默认值),就不会使用I/O从属进程完成备份。相反,完成备份的专用服务器进程会直接访问磁带设备。

       DBWR_IO_SLAVES:这个参数指定了DBW0 进程所用I/O 从属进程的个数。DBW0 进程及其从属进程总是将缓冲区缓存中的脏块写至磁盘。这个值默认为0,表示不使用I/O 从属进程。注意,如果将这个参数设置为一个非0 的值,LGWR 和ARCH 也会使用其自己的I/O 从属进程,LGWR 和ARCH 最多允许4 个I/O 从属进程。

       DBWR I/O 从属进程的名字是I1nn,LGWRI/O 从属进程的名字是I2nn,这里nn 是一个数。


3.2 并行查询从属进程

       Oracle7.1.6 引入了并行查询功能。这个功能是指:对于SELECT、CREATE TABLE、CREATE INDEX、UPDATE 等SQL 语句,创建一个执行计划,其中包含可以同时完成的多个(子)执行计划。将每个执行计划的输出合并在一起构成一个更大的结果。其目标是仅用少量的时间来完成操作,这只是串行完成同一操作所需时间的一小部分。

       例如,假设有一个相当大的表,分布在10 个不同的文件上。你配置有16 个CPU,并且需要在这个表上执行一个即席查询。另一种方法是:可以将这个查询计划分解为32 个小部分,并充分地利用机器;而不是只使用一个进程串行地读取和处理所有数据。相比之下,前一种做法要好得多。

       使用并行查询时,会看到名为Pnnn 的进程,这些就是并行查询从属进程。处理一条并行语句时,服务器进程则称为并行查询协调器(parallelquery coordinator)。操作系统上服务器进程的名字并不会改变,但是阅读有关并行查询的文档时,如果提到了协调器进程,你应该知道这就是原来的服务器进程。