Server Process是客户端在数据库服务器端操作的代表。任何操作,从SQL语句的传递执行,到数据块读取修改,都是通过Server Process完成的。
Server Process与Session之间的关系是什么样的呢?
基础说明
笔者在之前的Blog里,谈到过客户端应用通过Oracle Net Service连接到监听器,之后在一个端口建立与Server Process的联系。下面就几个方面重点重述一下:
首先,客户端并不能够直接同Oracle实例进行联系,即使客户端与服务器在同一台机器上。客户端对数据库的操作,是通过Oracle实例管理下的服务进程Server Process来完成的。所有客户端请求的操作,都是间接通过Server Process来实现数据块的获取和访问修改;
其次,客户端通过本地命名服务,并不是直接连接Server Process,是通过监听器进行重定向的过程。本地命名服务包括的是服务器主机名、连接服务名和端口号。客户端根据本地命名服务对应的连接信息,实际上首先连接到守候在端口的监听程序。监听器程序是一个独立的进程,运行在数据库服务器所在的主机上,维护着一个服务注册列表。
当监听程序受到客户端的请求之后,首先检查请求的服务是否在自身的注册(动静态注册)列表中。如果存在,则开始寻找一个对应实例的Server Process与请求匹配。
下面的过程,不同的Oracle连接方式存在一些区别。Oracle连接方式有专用dedicated和共享Shared两种。
在专用方式的时候,监听程序会让操作系统fork出一个新的Oracle Server Process,并且将这个新的Server Process的信息传递给客户端,并且协商出一个新的端口用于两者的通信。客户端在获取到这些信息之后,重建与Server Process在新端口建立联系。当会话完成,客户端断开连接之后,Server Process会自动被实例回收释放。
在共享方式下,还存在一个Dispatcher的进程,监听器是和Dispatcher请求一个Server Process,而Dispatcher会根据当前的情况,分发给一个Server Process与客户端通信。这种方式下,Server Process是为多个客户端共享。连接断开后,Server Process可能也不会被回收。
下面进行的实验,是在Linux的CentOS系统下进行的实验。在Windows和Unix/Linux下,Oracle实现的体系结构是完全不同的。最大的区别就是进程模式和线程模式。在Unix/Linux下,进程间通信、共享内存的机制是非常成熟的,所以我们常常听到的Server Process、各个后台进程是可以以进程的方式加以实现。SGA也可以真正做成一个内存共享区域。
而在Windows平台上,进程之前通信和共享内存是比较困难的,而且如果实现起来性能上有一些问题。所以Oracle的设计者们在Windows平台上做出了一些折中。将Linux下的各个进程和SGA,合并成Windows下的一个Oracle.exe进程,各个后台进程实现为Oracle进程下的线程单元。
为了更清楚的看到结构信息,我选择Linux平台进行演示。
专用dedicated模式
在专用模式下,一个客户对应的Server应该是一个。
首先,当我们启动了实例之后,发现Oracle实例的情况如下:
[oracle@oracle11g ~]$ ps -ef | grep ora | grep -v grep
root553955070 08:25 pts/000:00:00 su oracle
oracle554055390 08:25 pts/000:00:00 bash
oracle556110 08:31 ?00:00:00 /u01/oracle/bin/tnslsnr LISTENER -inherit
oracle561210 08:33 ?00:00:00 ora_pmon_wilson
oracle561410 08:33 ?00:00:00 ora_vktm_wilson
oracle561810 08:33 ?00:00:00 ora_gen0_wilson
oracle562010 08:33 ?00:00:00 ora_diag_wilson
oracle562210 08:33 ?00:00:00 ora_dbrm_wilson
oracle562410 08:33 ?00:00:00 ora_psp0_wilson
oracle562610 08:33 ?00:00:01 ora_dia0_wilson
oracle562810 08:33 ?00:00:00 ora_mman_wilson
oracle563010 08:33 ?00:00:00 ora_dbw0_wilson
oracle563210 08:33 ?00:00:00 ora_lgwr_wilson
oracle563410 08:33 ?00:00:01 ora_ckpt_wilson
oracle563610 08:33 ?00:00:01 ora_smon_wilson
oracle563810 08:33 ?00:00:00 ora_reco_wilson
oracle564010 08:33 ?00:00:02 ora_mmon_wilson
oracle564210 08:33 ?00:00:01 ora_mmnl_wilson
oracle564410 08:33 ?00:00:00 ora_d000_wilson
oracle564610 08:33 ?00:00:00 ora_s000_wilson
oracle567510 08:33 ?00:00:00 ora_qmnc_wilson
oracle568910 08:33 ?00:00:01 ora_cjq0_wilson
oracle570310 08:34 ?00:00:00 ora_q000_wilson
oracle570710 08:34 ?00:00:00 ora_q001_wilson
oracle572710 08:38 ?00:00:00 ora_smco_wilson
oracle578210 08:48 ?00:00:00 ora_w000_wilson
oracle586655400 09:04 pts/000:00:00 ps –ef
ps –ef命令,用于显示当前系统线程情况。Grep ora用于获取与oracle相关的进程列表。
额外解释一下各个列的含义:第一列为owner,表示该进程的所有者和执行者。第二列表是进程编号PID,是系统中对进程的唯一标志。第三列为PPID表示启动该进程的父进程PID编号,如果为1,表示是通过init程序加以启动的进程。最后一列表示启动进程的命令行以及进程名称。
通过上面的情况,我们可以关注两个部分:
其一为标注蓝色的部分:PID=5561,表示监听器程序进程;其二为红色部分,表示数据库实例的各个后台进程。如ora_pmon_wilson为实例的PMON进程,维护实例正常工作。
此外,可以观察SGA共享内存情况。
[oracle@oracle11g ~]$ ipcs
------ Shared Memory Segments --------
keyshmidownerpermsbytesnattchstatus
0xd4d89218 32768oracle66040960//共享区信息
------ Semaphore Arrays --------
keysemidownerpermsnsems
0x89c98dc4 98304oracle660154
------ Message Queues --------
keymsqidownerpermsused-bytesmessages
当我们发起一个连接,使用一个sqlplus客户端连接。
//建立个一个连接
SQL> conn sys/sys@wilson as sysdba;
已连接。
SQL> select sid from v$mystat where rownum<2;
SID
----------
29
此时,进程情况。
[oracle@oracle11g ~]$ ps -ef | grep ora
oracle561210 08:33 ?00:00:00 ora_pmon_wilson
oracle561410 08:33 ?00:00:00 ora_vktm_wilson
。。。。。。(篇幅原因,省略)
oracle578210 08:48 ?00:00:00 ora_w000_wilson
oracle591010 09:12 ?00:00:00 oraclewilson (LOCAL=NO)
oracle591210 09:13 ?00:00:00 ora_j000_wilson
发现,进程列表中多出了一个名为oraclewilson的进程,SID编号为5910。
同时,查看数据库视图,可以发现。
//会话中,发现对应的会话记录;
SQL> select sid, paddr, username, machine, action from v$session where username='SYS';
SID PADDRUSERNAMEMACHINEACTION
---------- -------- ---------------------------------------------------------------
29 38BC6C94 SYSWORKGROUP\WWW-0E6111DFF74
//SID=29,与登录会话相同;
PADDR=38BC6C94,为进程的物理地址。根据这个地址,我们查找v$process视图。
//根据进程的地址,搜索对应记录;
SQL> select addr, spid, program from v$process where addr='38BC6C94';
ADDRSPIDPROGRAM
-------- ------------------------------------------------
38BC6C945910oracle@oracle11g
发现对应的地址的SPID为5910,恰恰为多出来的oraclewilson进程的SID。说明,登录SYS的会话(SID=29)对应唯一的一个Server Process,PID=5910。
当关闭该窗口,退出登录后。Server Process消失。
[oracle@oracle11g ~]$ ps -ef | grep ora
root553955070 08:25 pts/000:00:00 su oracle
oracle554055390 08:25 pts/000:00:00 bash
oracle556110 08:31 ?00:00:00 /u01/oracle/bin/tnslsnr LISTENER -inherit
oracle561210 08:33 ?00:00:00 ora_pmon_wilson
。。。。。。(篇幅原因,省略)
oracle646610 09:24 ?00:00:00 ora_j001_wilson
oracle646755400 09:24 pts/000:00:00 ps -ef
oracle646855400 09:24 pts/000:00:00 grep ora
结论:在专用模式下,一个Server Process是与客户端连接、会话一一对应的。同时建立,同时消亡。
下面我们分析一下PLSQL Developer的连接特点和过程。