1、共享服务器体系结构
共享服务器由作为指定实例一部分的其他进程实现。这些进程是在实例启动阶段被启动的后台进程。此时存在两种新进程:调度进程和共享服务器进程。SGA内还存在一些特殊的队列存储结构。
启动共享服务器的实例时,除了启动常见的后台进程,还会启动一个或多个调度进程,与其他TCP进程一样,调度进程在操作系统的端口映射程序所分配的一个单一TCP端口上运行,并且使用侦听器LOCAL_LISTENER参数与指定的侦听器相联系并向其进行注册。此时还会启动一个或多个服务器进程。
上述进程类似于一个普通的专用服务器进程,只不过不依赖于会话。这些进程会接收、分析和执行SQL语句以及产生结果集,但它们并不是直接从一个用户进程接收SQL语句,而是从一个队列中读取这些语句,这个队列填充了来自任意数目用户进程的SQL语句。同样,共享服务器并不直接将结果集取回至一个用户进程,而将结果集填入一个响应队列。
问题来了,用户进程生成的SQL语句怎样进入被服务器进程读取的队列?结果集怎样被取回至用户进程?此时就需要使用调度程序。用户进程联系侦听器时,侦听器的动作是传回某个调度程序的地址,而不是启动一个服务器进程与这个用户进程联系在一起。只存在一个调度进程,那侦听器会连接这个调度进程与所有用户的连接。如果存在多个调度进程,那么侦听器会在这些调度进程之间实现对引入连接请求的负载均衡,最终结果是许多用户进程分别连接一个调度进程。
为了保护一个会话,与调度进程的连接必须持久,而与侦听器的连接可以是短暂的。
用户进程生成一条SQL语句时,这条语句会被发送至调度进程。调度进程将其接收到的所有SQL语句放入一个队列。因为所有调度进程共享这个队列,所以该队列被称为“公共”队列。所有共享服务器进程都监视公共队列。在一条SQL语句到达公共队列时,第一个可用的共享服务器会获取这条语句。随后的语句执行过程会经过通常的分析-绑定-执行阶段,不过进入取出阶段时,因为用户进程与这个共享服务器之间不存在连接,所以共享服务器无法将结果集取回至用户进程。此时,共享服务器只能将结果放入最初接收到指定作业的调度进程专用的响应队列。每个调度进程都会监视自己的响应队列,一旦在响应队列中放入了结果集,相应的调度进程就会获得结果集并将其返回至先前发出SQL语句的用户进程。
所有调度进程共享一个公共的输入队列,但是每个调度进程都具有自己的响应队列。
调度进程与队列机制的一个结果是任何可用的共享服务器都能够执行来自己任何用户进程的任何SQL语句。又有一问题,怎么处理锁定状态的呢?为了解决这问题,共享服务器会话在共享池中(而不是在PGA中)存储大量的会话数据。只要某个共享服务器从公共队列中获取一个作业,那么就会进入SGA并连接适当的内存块,从而找出会话的状态。SGA中用于每个共享服务器会话的内存被称为用户全局区(User Global Area,简写UGA)。除了会话的堆栈空间之外,UGA还包含了PGA中的所有存储结构,并且是进行存储器存储的来源。
在共享服务器中,不进入SGA的PGA存储结构为堆栈空间。
2、配置共享服务器
在服务器端,共享服务器与数据库无关,而是只与实例有关。通过动态实例注册,侦听器会被自动配置以用于共享服务器。可以断定:共享服务器通过实例初始化参数进行配置。虽然存在若干可选的实例参数,但只有一个参数是必需的。
用于共享服务器的实例参数
参数 | 是否必须 | 高级参数或基本参数 |
SHARED_SERVERS | 否 | 基本参数 |
DISPATCHERS | 是 | 高级参数 |
MAX_SHARED_SERVERS | 否 | 高级参数 |
MAX_DISPATCHERS | 否 | 高级参数 |
LOCAL_LISTENER | 否 | 高级参数 |
LARGE_POOL_SIZE | 否 | 高级参数 |
CIRCUITS | 否 | 高级参数 |
SHARED_SERVER_SESSIONS | 否 | 高级参数 |
PROCESSES | 否 | 基本参数 |
SESSIONS | 否 | 基本参数 |
无论是否为高级参数,只要使用了共享服务器,就应当设置实例参数SHARED_SERVERS、DISPATCHERS和LARGE_POOL_SIZE。在任何情况下始终应当设置的实例参数为PROCESSES和SESSIONS。此外,如果侦听器没有使用1521端口,那么还必须设置实例参数LOCAL_LISTENER。
配置共享服务器:
############################################### # 启动监听,启动实例,用命令设置启用共享服务器 ############################################### $ lsnrctl start $ sqlplus / as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Oct 3 21:19:10 2008 Copyright (c) 1982, 2005, Oracle. All rights reserved. Connected to an idle instance. SQL> startup ORACLE instance started. Total System Global Area 264241152 bytes Fixed Size 1218868 bytes Variable Size 88082124 bytes Database Buffers 171966464 bytes Redo Buffers 2973696 bytes Database mounted. Database opened. SQL> alter system set 2 dispatchers='(protocol=tcp)(dispatchers=2)' 3 scope=spfile; System altered. SQL> alter system set shared_servers=3 scope=spfile; System altered. SQL> startup force; ORACLE instance started. Total System Global Area 264241152 bytes Fixed Size 1218868 bytes Variable Size 88082124 bytes Database Buffers 171966464 bytes Redo Buffers 2973696 bytes Database mounted. Database opened. ############################################### # 确认启动调度进程与共享服务器进程 # 可以看到调度进程(D000、D001)和三个共享服务器进程(S001、S002、S003) # 书上共享服务器进程S开头,我电脑上怎么P开头? ############################################### SQL> select program from v$process; SQL> exit ############################################### # 下面的输入相似就行了,lsnrctl确认侦听器注册了调试进程 ############################################### $ lsnrctl services LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 03-OCT-2008 21:20:22 Copyright (c) 1991, 2005, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1))) Services Summary... Service "PLSExtProc" has 1 instance(s). Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service Handler(s): "DEDICATED" established:0 refused:0 LOCAL SERVER Service "ora" has 1 instance(s). Instance "ora", status READY, has 3 handler(s) for this service... Handler(s): "DEDICATED" established:0 refused:0 state:ready LOCAL SERVER "D001" established:0 refused:0 current:0 max:972 state:ready DISPATCHER <machine: OracleServer, pid: 3694> (ADDRESS=(PROTOCOL=tcp)(HOST=OracleServer)(PORT=60422)) "D000" established:0 refused:0 current:0 max:972 state:ready DISPATCHER <machine: OracleServer, pid: 3692> (ADDRESS=(PROTOCOL=tcp)(HOST=OracleServer)(PORT=39547)) Service "ora_XPT" has 1 instance(s). Instance "ora", status READY, has 3 handler(s) for this service... Handler(s): "DEDICATED" established:0 refused:0 state:ready LOCAL SERVER "D001" established:0 refused:0 current:0 max:972 state:ready DISPATCHER <machine: OracleServer, pid: 3694> (ADDRESS=(PROTOCOL=tcp)(HOST=OracleServer)(PORT=60422)) "D000" established:0 refused:0 current:0 max:972 state:ready DISPATCHER <machine: OracleServer, pid: 3692> (ADDRESS=(PROTOCOL=tcp)(HOST=OracleServer)(PORT=39547)) The command completed successfully ############################################### # 远程连接,通过侦听器登录实例 ############################################### C:/>sqlplus test/test@ora SQL*Plus: Release 10.2.0.3.0 - Production on 星期五 10月 3 20:23:13 2008 Copyright (c) 1982, 2006, Oracle. All Rights Reserved. 连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options ############################################### # 查询会返回一条记录,说明新会话经过调试进程以及会话地址 # 我这里没成功,可能是版本问题,别人在10.1的版本上成功查询出结果,我的10.2版本 ############################################### SQL> select dispatcher, saddr, circuit from v$circuit; |
3、监视共享服务器
下面介绍的视图能说明共享服务器环境的状态。
V$CIRCUIT视图:给出一条记录说明通过共享服务器的所有并发连接。其中,CIRCUIT列是唯一标识符。通过连接这个列与V$SESSION视图中的SADDR列以及V$DISPATCHER视图中的DISPATCHER列,可以将会话映射至调度进程。
V$SHARED_SERVER视图:每个共享服务器进程状态。其中,IDLE和BUSY列说明了每个进程实际服务于讲求所花费的时间量,而不是等待作业到达公共队列所花的时间量。
V$DISPATCHER视图:为每个调度进程给出一条记录。重要点的列IDLE和BUSY。
V$SHARED_SERVER_MONTTOR视图:给出一记录说明经过共享服务器的最大连接数与最大会话数(通常相同)。此外,该记录还说明已被动态启动的共享服务器进程数。如果这个数大于零,说明最初没有启动足够多的共享服务器进程。
V$QUEUE视图:给出一条用于公共队列的记录以及一条用于所有调度进程的响应队列的记录。QUEUE列十分重要,这个列说明队列中数据项的数目。记住,理想情况下应当不存在排队。如果公共队列中存在数据项,说明没有足够的共享服务器进程被用于清空队列。如果响应队列中存在数据项,说明调度进程处理超负荷状态。
V$MTS视图:提供向后兼容能力。和V$SHARED_SERVER_MONTTOR视图完全相同。