第5章 Oracle进程
现在要谈到Oracle体系结构的最后一部分了。我们已经研究了数据库以及构成数据库的物理文件集。讨论Oracle使用的内存时,我们分析了实例的前半部分。Oracle体系结构中还有一个问题没有讲到,这就是构成实例另一半的进程(process)集。
Oracle中的各个进程要完成某个特定的任务或一组任务,每个进程都会分配内部内存(PGA内存)来完成它的任务。Oracle实例主要有3类进程:
q 服务器进程(server process):这些进程根据客户的请求来完成工作。我们已经对专用服务器和共享服务器有了一定的了解。它们就是服务器进程。
q 后台进程(background process):这些进程随数据库而启动,用于完成各种维护任务,如将块写至磁盘、维护在线重做日志、清理异常中止的进程等。
q 从属进程(slave process):这些进程类似于后台进程,不过它们要代表后台进程或服务器进程完成一些额外的工作。
其中一些进程(如数据库块写入器(DBWn)和日志写入器(LGWR))在前面已经提到过,不过现在我们要更详细地介绍这些进程的功能,说明这些进程会做什么,并解释为什么。
注意 这一章谈到“进程”时,实际上要把它理解为两层含义,在某些操作系统(如Windows)上,Oracle使用线程实现,所以在这种操作系统上,就要把我们所说的“进程”理解为“线程”的同义词。在这一章中,“进程”一词既表示进程,也涵盖线程。如果你使用的是一个多进程的Oracle实现,比如说UNIX上的Oracle实现,“进程”就很贴切。如果你使用的是单进程的Oracle实现,如Windows上的Oracle实现,“进程”实际是指“Oracle进程中的线程”。所以,举例来说,当我谈到DBWn进程时,在Windows上就对应为Oracle进程中的DBWn线程 。
5.1 5.1 服务器进程
服务器进程就是代表客户会话完成工作的进程。应用向数据库发送的SQL语句最后就要由这些进程接收并执行。
在第2章中,我们简要介绍了两种Oracle连接,包括:
q 专用服务器(dedicated server)连接,采用专用服务器连接时,会在服务器上得到针对这个连接的一个专用进程。数据库连接与服务器上的一个进程或线程之间存在一对一的映射。
q 共享服务器(shared server)连接,采用共享服务器连接时,多个会话可以共享一个服务器进程池,其中的进程由Oracle实例生成和管理。你所连接的是一个数据库调度器(dispatcher),而不是特意为连接创建的一个专用服务器进程。
注意 有一点很重要,要知道Oracle术语中连接和会话之间的区别。连接(connection)就是客户进程与Oracle实例之间的一条物理路径(例如,客户与实例之间的一个网络连接)。会话(session)则不同,这是数据库中的一个逻辑实体,客户进程可以在会话上执行SQL等。多个独立的会话可以与一个连接相关联,这些会话甚至可以独立于连接存在。稍后将进一步讨论这个问题。
专用服务器进程和共享服务器进程的任务是一样的:要处理你提交的所有SQL。当你向数据库提交一个SELECT * FROM EMP查询时,会有一个Oracle专用/共享服务器进程解析这个查询,并把它放在共享池中(或者最好能发现这个查询已经在共享池中)。这个进程要提出查询计划,如果必要,还要执行这个查询计划,可能在缓冲区缓存中找到必要的数据,或者将数据从磁盘读入缓冲区缓存中。
这些服务器进程是干重活的进程。在很多情况下,你都会发现这些进程占用的系统CPU时间最多,因为正是这些进程来执行排序、汇总、联结等等工作,几乎所有工作都是这些进程做的。
5.1.1 专用服务器连接
在专用服务器模式下,客户连接和服务器进程(或者有可能是线程)之间会有一个一对一的映射。如果一台UNIX主机上有100条专用服务器连接,就会有相应的100个进程在执行。可以用图来说明,如图5-1所示。
客户应用中链接着Oracle库,这些库提供了与数据库通信所需的API。这些API知道如何向数据库提交查询,并处理返回的游标。它们知道如何把你的请求打包为网络调用,专用服务器则知道如何将这些网络调用解开。这部分软件称为Oracle Net,不过在以前的版本中可能称之为SQL*Net或Net8。这是一个网络软件/协议,Oracle利用这个软件来支持客户/服务器处理(即使在一个n层体系结构中也会“潜伏”着客户/服务器程序)。不过,即使从技术上讲没有涉及Oracle Net,Oracle也采用了同样的体系结构。也就是说,即使客户和服务器在同一台机器上,也会采用这种两进程(也称为两任务)体系结构。这个体系结构有两个好处:
图5-1 典型的专用服务器连接
q 远程执行(remote execution):客户应用可能在另一台机器上执行(而不是数据库所在的机器),这是很自然的。
q 地址空间隔离(address space isolation):服务器进程可以读写SGA。如果客户进程和服务器进程物理地链接在一起,客户进程中一个错误的指针就能轻松地破坏SGA中的数据结构。
我们在第2章中了解了这些专用服务器如何“产生”,也就是如何由Oracle监听器进程创建它们。这里不再介绍这个过程;不过,我们会简要地说明如果不涉及监听器会是什么情况。这种机制与使用监听器的机制基本上是一样的,但不是由监听器通过fork()/exec()调用(UNIX)或进程间通信IPC调用(Windows)来创建专用服务器,而是由客户进程自己来创建。
注意 有多种fork()和exec()调用,如vfork()、execve()等。Oracle所用的调用可能根据操作系统和实现的不同而有所不同,但是最后的结果是一样的。fork()创建一个新进程,这是父进程的一个克隆,而且在UNIX上这也是创建新进程的惟一途径。exec()在内存中现有的程序映像上加载一个新的程序映像,这就启动了一个新程序。所以SQL*Plus可以先“fork”(即复制自身),然后“exec”Oracle二进制可执行程序,用这个新程序覆盖它自己的副本。
在UNIX上,可以在同一台机器上运行客户和服务器,就能很清楚地看出这种父/子进程的创建:
ops$tkyte@ORA 10G > select a.spid dedicated_server, 2 b.process clientpid 3 from v$process a, v$session b 4 where a.addr = b.paddr 5 and b.sid = (select sid from v$mystat where rownum=1) 6 / DEDICATED_SE CLIENTPID ----------------------- ---------------- 5114 5112
ops$tkyte@ORA 10G > !/bin/ps -p 5114 5112 PID TTY STAT TIME COMMAND 5112 p ts/1 R 0:00 sqlplus 5114 ? S 0:00 oracleora 10g (DESCRIPTION=(LOCAL=YES)..(PROTOCOL=beq))) |
在此,我使用了一个查询来发现与专用服务器相关联的进程ID(PID),从V$PROCESS得到的SPID是执行该查询时所用进程的操作系统PID。
5.1.2 共享服务器连接
下面更详细地介绍共享服务器进程。共享服务器连接强制要求必须使用Oracle Net,即使客户和服务器都在同一台机器上也不例外。如果不使用Oracle TNS监听器,就无法使用共享服务器。如前所述,客户应用会连接到Oracle TNS监听器,并重定向或转交给一个调度器。调度器充当客户应用和共享服务器进程之间的“导管”。图5-2显示了与数据库建立共享服务器连接时的体系结构。
图5-2 典型的共享服务器连接
在此可以看到,客户应用(其中链接了Oracle库)会与一个调度器进程物理连接。对于给定的实例,可以配置多个调度器,但是对应数百个(甚至数千个)用户只有一个调度器的情况并不鲜见。调度器只负责从客户应用接收入站请求,并把它们放入SGA中的一个请求队列。第一个可用的共享服务器进程(与专用服务器进程实质上一样)从队列中选择请求,并附加相关会话的UGA(图5-2中标有“S”的方框)。共享服务器处理这个请求,把得到的输出放在响应队列中。调度器一直监视着响应队列来得到结果,并把结果传回给客户应用。就客户而言,它分不清到底是通过一条专用服务器连接还是通过一条共享服务器连接进行连接,看上去二者都一样,只是在数据库级二者的区别才会明显。
5.1.3 连接与会话
连接并不是会话的同义词,发现这一点时很多人都很诧异。在大多数人眼里,它们都是一样的,但事实上并不一定如此。在一条连接上可以建立0个、一个或多个会话。各个会话是单独而且独立的,即使它们共享同一条数据库物理连接也是如此。一个会话中的提交不会影响该连接上的任何其他会话。实际上,一条连接上的各个会话可以使用不同的用户身份!
在Oracle中,连接只是客户进程和数据库实例之间的一条特殊线路,最常见的就是网络连接。这条连接可能连接到一个专用服务器进程,也可能连接到调度器。如前所述,连接上可以有0个或多个会话,这说明可以有连接而无相应的会话。另外,一个会话可以有连接也可以没有连接。使用高级Oracle Net特性(如连接池)时,客户可以删除一条物理连接,而会话依然保留(但是会话会空闲)。客户在这个会话上执行某个操作时,它会重新建立物理连接。下面更详细地定义这些术语:
q 连接(connection):连接是从客户到Oracle实例的一条物理路径。连接可以在网络上建立,或者通过IPC机制建立。通常会在客户进程与一个专用服务器或一个调度器之间建立连接。不过,如果使用Oracle的连接管理器(Connection Manager ,CMAN),还可以在客户和CMAN之间以及CMAN和数据库之间建立连接。CMAN的介绍超出了本书的范围,不过Oracle Net Services Administrator’s Guide(可以从http://otn.oracle.com免费得到)对CMAN有详细的说明。
q 会话(session):会话是实例中存在的一个逻辑实体。这就是你的会话状态(session state),也就是表示特定会话的一组内存中的数据结构。提到“数据库连接”时,大多数人首先想到的就是“会话”。你要在服务器中的会话上执行SQL、提交事务和运行存储过程。
可以使用SQL*Plus来看一看实际的连接和会话是什么样子,从中还可以了解到,实际上一条连接有多个会话的情况相当常见。这里使用了AUTOTRACE命令,并发现有两个会话。我们在一条连接上使用一个进程创建了两个会话。以下是其中的第一个会话:
ops$tkyte@ORA 10G > select username, sid, serial#, server, paddr, status 2 from v$session 3 where username = USER 4 / USERNAME SID SERIAL# SERVER PADDR STATUS --------- ---- -------- --------- -------- -------- OPS$TKYTE 153 3196 DEDICATED AE4CF614 ACTIVE |
这说明现在有一个会话:这是一个与单一专用服务器连接的会话。以上PADDR列是这个专用服务器进程的地址。下面,只需打开AUTOTRACE来查看SQL*Plus中所执行语句的统计结果:
ops$tkyte@ORA 10G > set autotrace on statistics ops$tkyte@ORA 10G > select username, sid, serial#, server, paddr, status 2 from v$session 3 where username = USER 4 /
USERNAME SID SERIAL# SERVER PADDR STATUS --------- ---- -------- --------- -------- -------- OPS$TKYTE 151 1511 DEDICATED AE4CF614 INACTIVE OPS$TKYTE 153 3196 DEDICATED AE4CF614 ACTIVE
Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 0 consistent gets 0 physical reads 0 redo size 756 bytes sent via SQL*Net to client 508 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 2 rows processed |