
3.4 Oracle数据库服务器支持的两种连接方式
Oracle提供了两种数据库连接方式,一种是专有连接方式,另一种是共享连接方式,二者的区别在于对服务器进程的拥有模式,专有连接方式是一个用户连接对应一个数据库服务器进程,而共享连接方式中多个用户可以使用一个数据库服务器(严格意义上讲是分时复用),使用共享服务器模式对于事务执行时间短且服务器资源受限的系统是有利的,但是对于Oracle依然推荐使用专有连接方式,这种方式会耗费内存资源(PGA),但是一个连接对应一个服务器进程专有服务,减少竞争,对于长事务尤其有用。
3.4.1 服务器进程
Oracle提供了两种网络连接方式,一种是专有连接,另一种是共享连接,针对这两种连接方式Oracle对应两种数据库服务器:专有服务器和共享服务器。无论是哪种连接方式,都需要服务器进程的参与,服务器进程是代表客户完成数据库访问工作的进程,客户端的SQL语句都是通过这些服务器进程来接收并执行的。
● 专有服务器:采用专有服务器时,数据库服务器会针对每一个连接产生一个服务器进程,这个进程就是专属这个连接的。数据库连接与服务器上的一个进程或线程之间是一一对应的关系。
● 共享服务器:采用共享服务器时,数据库服务器的一个服务器进程服务于多个会话,即使用服务器进程池(有多个服务器进程)为多个会话服务,在建立连接时,客户端会首先连接到调度器,由调度器协调数据库服务器的资源。
3.4.2 共享连接
在共享服务器模式下,用户进程与服务器进程是多对多的关系,多个服务器进程会处理多个用户进程。在使用共享服务器连接时,必须使用Oracle Net协议软件,如果不使用Oracle 监听器,则无法使用共享服务器。
整个共享连接的过程是客户发起连接,监听器处理连接并将连接重定向或者转交给一个调度器,调度器再协调共享服务器资源,如图3-1所示。

图3-1 共享服务器连接示意图
在上图中,多个客户端通过网络发起连接,目标是连接到Oracle数据库,此时客户应用程序会与一个调度器DISPATCHER建立物理连接。调度器可以配置多个,也可以只配置一个,因为调度器的任务不是很重,它负责接受客户请求,并将客户请求放入SGA的请求队列,然后调度器会不断地监视响应队列,一旦查询结果返回则把结果传给用户。
共享服务器进程一旦空闲,则从请求队列获取用户请求,处理这个请求,将数据放回响应队列。而对于客户而言,这些操作都是透明的,无论使用专有服务器连接还是共享服务器连接,其实对于客户而言感受不到不同服务器架构的存在,只是在特定的数据库应用环境下,需要考虑专有服务器连接和共享服务器连接的优劣,选择合适的网络连接方式。
3.4.3 共享连接涉及初始化参数
共享服务器中涉及很多参数如调度器、共享服务器、会话等,本节我们讨论这些参数的作用以及含义。
● 调度器(DISPATCHERS):负责将用户请求传递放入SGA,并负责监控SGA中的响应队列,如果有返回数据则将数据返回给用户。
● 共享服务器进程(Shared_servers):该参数设置共亨服务器进程的数量。
● 最大共享服务器进程(Max_shared_servers):该参数设置数据库服务器支持的最多的服务器进程数量。
● 共享服务器会话数(shared_server_sessions):该参数设置当前数据库服务器在共享模式下的最大会话数。而专用会话数=sessions-共享会话数。
3.4.4 共享连接的工作过程
共享连接模式下,需要配置多个名为dispatcher的组件,dispatcher作为用户进程和服务器进程之间的协调者,负责将用户进程的请求传递给服务器进程,并将服务器进程得到的结果返回给用户。
PMON定期将每个dispatcher的地址,以及工作负载注册到监听器里面,当用户进程连接监听器时,监听器会选择一个负载最低的dispatcher,并把该dispatcher的地址返回给用户进程,用户进程和dispatcher进程建立连接,在session的整个生命期间,用户进程所连接的dispatcher不会发生改变。
整个连接如图3-2所示。

图3-2 共享连接流程图
01 用户进程连接到监听器。
02 监听器根据注册的各个dispatcher的负载情况,选择一个负载最低的dispatcher,并将其地址返回给用户进程。
03 用户进程根据监听器返回的dispatcher地址,连接到该dispatcher。
04 dispatcher接收到用户进程发出的请求以后,会将该请求放入请求队列,请求队列位于SGA中,被所有的dispatcher共有。
05 在服务器进程中,最空闲的服务器进程会从请求队列中按照先进先出的原则,挑选一个请求进行处理。
06 服务器进程处理请求后,得到的结果放入响应队列,Oracle为每个dispatcher分配一个对应的响应队列。
07 dispatcher到相应的队列中取出结果,返回给用户进程。
共享连接中,多个服务器进程会处理多个用户请求,用户的PGA就需要在不同的服务器进程之间共享,PGA中的UGA部分就会被放入到SGA中,如果配置了large pool,则UGA会在large pool里分配,没有配置large pool,那么UGA就放在shared pool里面分配。
3.4.5 共享连接的配置
共享连接设计的组件有DISPATCHERS、shared_servers、max_shared_servers、shared_server_sessions。
1.配置DISPATCHER进程的数量
DISPATCHERS初始化参数是用来配置DISPATCHERS进程信息的,如连接使用协议、DISPATCHERS进程数量、使用端口等。下面是典型的DISPATCHERS配置例子。
例子3-24 配置DISPATCHERS
SQL> alter system set dispatchers='(protocol=tcp)(dispatchers=3)'; System altered.
对于DISPATCHERS进程有三类属性设置需要考虑(有的是可选的)。
(1)协议地址,该属性有三个参数设置。
● ADDRESS:DISPATCHERS监听所在网络地址。
● DESCRIPTION:DISPATCHERS监听所在网络地址描述,包括网络协议地址。
● PROTOCOL:指明DISPATCHERS使用的网络协议。
(2)指定DISPATCHERS的数量。使用DISPATCHERS参数。
在设置DISPATCHERS进程信息时,也可以指定在哪个地址上创建监听,如下所示。
DISPATCHERS=’(ADDRESS=(PROTOCOL=TCP)(HOST=144.25.16.201))(DISPATCHERS=2)’
在设置该参数时,需要考虑max_dispatchers参数,这个参数限制了DISPATCHERS的最大数量。如下例所示,我们限制这个最大数值为5。
例子3-25 设置参数最大值
SQL> alter system set max_dispatchers=5; System altered.
2.共享服务器进程的数量
参数shared_servers设置当前数据库服务器启动的共享服务器数量,而参数max_shared_servers设置当前数据库服务器支持的最大共享服务器数量。下面我们修改这个两个值。
例子3-26 修改参数
SQL> alter system set shared_servers=5; System altered. SQL> alter system set max_shared_servers=20; System altered. Shared_servers ,max_shared_servers。
我们设置当前共享数据库服务器进程数量为5,而最大共享服务器数量为20;
服务器进程动态调整,首先是分配默认的数量,根据负载适当地增加,当负载下降的时候,适当减少服务器进程的数量。但是增加和减少的数量控制在上面的两个参数之间。
3.配置共享会话数
我们需要设置Oracle分配给共享会话的连接数量,设置shared_server_sessions参数,该参数的设置与SESSIONS参数有关,SESSIONS参数指定了数据库最大的会话数,那么共享会话就不能超过SESSIONS参数指定的值,而“专有连接数量=SESSIOS-共享连接数”。
例子3-27 设置数据库的共享会话数为100
SQL> alter system set shared_servers_sessions=100; System altered.
例子3-28 查看当前的最大会话数是多少
SQL> show parameter sessions; NAME TYPE VALUE ------------------------------------ ------------------------------------------ ------------------------------ java_max_sessionspace_size integer 0 java_soft_sessionspace_limit integer 0 license_max_sessions integer 0 license_sessions_warning integer 0 logmnr_max_persistent_sessions integer 1 sessions integer 225 shared_server_sessions integer 100; System altered.
此时显示当前的最大会话数是225,那么专有连接数就是125。
那么如何设置SESSIONS呢,该参数又与参数PROCESSES优化,默认情况下按照如下的计算方式计算。
SESSIONS=(1.1*PROCESSES)+5
如果设置的SESSIONS值大于按照上述公式计算的值,则取前者,即取二者中的较大值;如果设置的SESSIONS值小于按照上述公式计算的值则取后者,同样取二者中的大值,比如下例。
例子3-29 查看当前的PROCESSES的值
SQL> show parameter processes; NAME TYPE VALUE ------------------------------------ -------------------------------- ------------------------------ aq_tm_processes integer 0 db_writer_processes integer 1 gcs_server_processes integer 0 job_queue_processes integer 10 log_archive_max_processes integer 2 processes integer 200
当前process的值为200,我们按照公式sessions=1.1*200+5=225进行计算,发现同我们查询的结果是一致的。
4.修改tnsnames.ora文件
tnsnames.ora文件具体修改过程,如下例所示。
例子3-30 修改tnsnames.ora文件
PROD = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = ocm1.oracle)(PORT = 1522)) ) (CONNECT_DATA = (SERVER = SHARED) (SERVICE_NAME = PROD) ) )
此时,可以使用本地连接方式,将数据库的动态注册到监听器LISTENER1。我们需要启动LISTENER1,然后查看该监听支持的服务,如下例所示。
例子3-31 查看监听支持的服务
[Oracle@ocm1 admin]$ lsnrctl service listener1 LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 26-OCT-2011 21:59:21 Copyright (c) 1991, 2005, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ocm1.oracle)(PORT=1522))) Services Summary... Service "PROD" has 1 instance(s). Instance "PROD", status READY, has 4 handler(s) for this service... Handler(s): "D002" established:0 refused:0 current:0 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11868> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32873)) "D001" established:0 refused:0 current:0 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11866> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32867)) "D000" established:1 refused:0 current:0 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11864> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32872)) "DEDICATED" established:0 refused:0 state:ready LOCAL SERVER Service "PROD_XPT" has 1 instance(s). Instance "PROD", status READY, has 4 handler(s) for this service... Handler(s): "D002" established:0 refused:0 current:0 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11868> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32873)) "D001" established:0 refused:0 current:0 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11866> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32867)) "D000" established:1 refused:0 current:0 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11864> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32872)) "DEDICATED" established:0 refused:0 state:ready LOCAL SERVER The command completed successfully
可见,启动了三个DISPATCHERS,但是没有一个连接建立。下面我们产生一个连接和一个会话,看此时的DISPATCHERS信息。
例子3-32 产生一个连接和一个会话
[Oracle@ocm1 admin]$ sqlplus sys/Oracle@prod as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Wed Oct 26 22:00:46 2011 Copyright (c) 1982, 2005, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, Oracle Label Security, OLAP and Data Mining options SQL>
此时,通过本地连接方式连接到数据库服务器,使用的是共享连接。接下来继续查看监听器LISTENER1的服务信息。
例子3-33 继续查看监听器的服务信息
[Oracle@ocm1 admin]$ lsnrctl service listener1; LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 26-OCT-2011 22:02:10 Copyright (c) 1991, 2005, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ocm1.oracle)(PORT=1522))) Services Summary... Service "PROD" has 1 instance(s). Instance "PROD", status READY, has 4 handler(s) for this service... Handler(s): "D002" established:0 refused:0 current:0 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11868> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32873)) "D001" established:1 refused:0 current:1 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11866> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32867)) "D000" established:0 refused:0 current:0 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11864> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32872)) "DEDICATED" established:0 refused:0 state:ready LOCAL SERVER Service "PROD_XPT" has 1 instance(s). Instance "PROD", status READY, has 4 handler(s) for this service... Handler(s): "D002" established:0 refused:0 current:0 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11868> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32873)) "D001" established:1 refused:0 current:1 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11866> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32867)) "D000" established:1 refused:0 current:0 max:1022 state:ready DISPATCHER <machine: ocm1.oracle, pid: 11864> (ADDRESS=(PROTOCOL=tcp)(HOST=ocm1.oracle)(PORT=32872)) "DEDICATED" established:0 refused:0 state:ready LOCAL SERVER The command completed successfully
上例黑体部分就是使用该DISPATCHERS建立的共享连接。
3.4.6 共享连接的一些问题
1.有些操作不能使用共享连接
● 启动关闭数据库实例。
● 创建表空间和数据文件。
● 维护表和索引等数据库的管理工作。
2.有些操作不适合共享服务器连接
共享服务器适合单纯的OLTP,对于需要扫描大量数据、运行时间较长的操作,不适合采用共享连接,例如备份恢复。
3.4.7 专有连接
在专有服务器模式下,客户连接与数据库服务进程之间是一对一的关系,一个客户连接对应一个服务器进程。
专有连接中,用户进程没有发出命令,服务器进程处于空闲状态,资源一直占用,共享模式中,只要是服务器进程空闲,就可以处理其他用户发出的命令,因此服务器进程的数量减少,对资源的利用更加高效,占用的PGA减少,可以支持更多的用户。这是共享服务器的优势,相反就是专有服务器的劣势了。
专有连接其实就是一个典型的客户-服务器2层架构。在应用程序中,客户应用程序通过API连接到数据库,而这些API知道如何将SQL查询传递给数据库,并处理返回的数据。这些API知道如何将数据库请求打包为网络调用,而专有服务器进程则知道如何解包这些网络应用。整个过程由一个被称为网络协议的软件或Oracle Net来支持。
图3-3是典型的专有服务器连接示意图。

图3-3 专有服务器连接示意图
在使用本地命名连接数据库时,默认使用专有连接,也可以显示设置的专有连接参数,如下例所示为TNSNAMES.ORA文件的内容。
例子3-34 TNSNAMES.ORA文件的内容
PROD = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = ocm1.oracle)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = DEDICATED) //DEDICATED说明是专有连接 (SERVICE_NAME = PROD) ) )
我们查看这个专有连接建立后,监听器记录的信息。
例子3-35 查看专有连接建立后,监听器记录的信息
[Oracle@ocm1 admin]$ lsnrctl service listener; LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 26-OCT-2011 22:12:08 Copyright (c) 1991, 2005, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ocm1.oracle)(PORT=1521))) Services Summary... Service "EMREP" has 1 instance(s). Instance "EMREP", status UNKNOWN, has 1 handler(s) for this service... Handler(s): "DEDICATED" established:0 refused:0 LOCAL SERVER Service "PROD" has 1 instance(s). Instance "PROD", status UNKNOWN, has 1 handler(s) for this service...//说明是静态注册 Handler(s): "DEDICATED" established:1 refused:0 //建立一个专有连接 LOCAL SERVER The command completed successfully