连接ORACLE服务器一般有两种方式:专用服务器连接(dedicated server)和共享服务器连接(shared server)。那么两者有啥区别和不同呢?下面我们将对这两者的区别与不同一一剖析。
专用服务器模式(dedicated server)
在专用服务器模式中,用户进程运行在客户端的机器上,专用服务器进程运行在数据库服务器,用户进程和专用服务器进程是两种不同类型的进程。
对于专用服务器模式,在用户登录时,ORACLE总会创建一个新的服务进程,这通常称为专用服务器配置。这个服务器进程会在会话生存期中专门为这个连接服务。对于每一个会话,都会生成一个新的专用服务器进程,会话与专用服务器进程之间存在一对一的映射关系。按照定义,这个专用服务器不是实例的一部分。用户进程(也就是想要连接数据库的程序)会通过某种网络通道(如TCP/IP Socket)与这个专用服务器进程直接通信,并由这个服务器进程接收和执行用户进程提交的SQL。用户进程与专用服务器进程是一一对应关系。默认使用专用模式
专用服务器模式(dedicated server)的一个很重要的特点就是UGA(用户全局域)是存储在PGA(进程全局域)中的,这个特性也很好说明了当前用户的内存空间是按照进程来进行分配的。
专用服务器模式适用场景:
1:只有少量的客户端连接系统或数据仓库系统。数据集市系统等
2:联机事务处理系统(OLTP)。当然联机事务处理系统必须要符合下面两个条件
A 用户连接请求数大于共享进程
B 事务大部分是长事务或者大事务
共享服务器模式(shared server)
共享服务器(shared server),正式的说法是多线程服务器(Multi-Threaded Server)或MTS。如果采用这种连接方式,就不会对每条用户连接创建另外的线程或新的进程。在连接建立的时候,Listener首先接收到客户端的建立连接的请求,然后Listener去生成一个叫做调度器(dipatcher)的进程与客户端进行连接。调度器把把客户端的请求放在SGA(系统全局域)的一个请求队列中,然后在共享服务器连接池中查找有无空闲的连接,然后让这个空闲的服务器进程进行处理。处理完毕以后再把处理结果返回给用户。共享服务器模式的请求流程如下所示
利用共享服务器,我们不必为10,000 个数据库会话创建10,000 个专用服务器(这样进程或线程就太多了),而只需建立很少的一部分进程/线程,顾名思义,这些进程/线程将由所有会话共享。这样Oracle 就能让更多的用户与数据库连接,否则很难连接更多用户。如果让我的机器管理10,000个进程,这个负载肯定会把它压垮,但是管理100 个或者1,000 个进程还是可以的。采用共享服务器模式,共享进程通常与数据库一同启动,使用ps命令可以看到这个进程。
数据库连接概述
共享服务器模式缺点:
采用专用服务器连接模式比采用共享服务器连接模式效率要高。因为ORACLE共享服务器方式也有诸多缺点。
1)共享服务器的代码路径比专用服务器长,所以它天生就比专用服务器慢。(这个观点来自David Dai博客)
2)存在人为死锁的可能,因为它是串行的,只要一个连接阻塞,则该服务器进程上的所有用户都被阻塞,并且极可能死锁。
3)存在独占事务的可能,因为如果一个会话的事务运行时间过长,它独占共享资源,其它用户只能等待,而专用服务器,每个客户端是一个会话。
4)共享服务器模式限制了某些数据库特性,例如:不能单独启动和关闭实例,不能进行介质恢复,不能使用Log Miner,并且SQL_TRACE没有意义(因为是共享而不是当前会话的)。共享服务服务器连接,会话的跟踪信息可能分布在不同的独立跟踪文件中,重建会话比较困难。除非必须要用共享模式,如系统负载太重或特定的性能,否则专用服务器是最佳选择。
共享服务器连接模式的优点在于服务器进程的数量可以得到控制,不大可能出现连接数过多而造成服务器内存崩溃。但是由于增加了复杂度以及请求相应的队列,可能性能上会有所下降。
MTS减少的内存实际上是专用服务器模式下每个用户连接到操作系统进程所需的内存,但它却使用SGA的Large_Pool来分配UGA,拆东墙补西墙,所减少的内存是很少的。如果用户会话的连接和断开很频繁,数据库进程的创建和删除的开销会非常大,这种情况最好采用共享服务器模式(否则,应该使用连接池技术)。如果客户端一次连接终身使用(会话生命周期内),使用共享服务器模式的意义不大。因为大部分时间,一个会话就连接到一个服务器进程,无法共享服务器进程。
判断数据库使用的连接模式
1:查看V$SESSION视图
SQL> select distinct server from v$session;
SERVER
---------
DEDICATED
NONE
如果SERVER字段的值除了DEDICATED,还有NONE,则说明当前实例启动了共享服务器,并且SERVER为NONE的会话正使用共享服务器连接,同时,如果只显示有DEDICATED,则不能说明服务器就一定工作在专用服务器下面,此时也有可能启动了共享模式。只是目前连接到数据库的都是专用服务器模式。
2:通过参数shared_server判断
如果shared_server值为0,则表示数据库没有启动共享服务模式。 这个参数是配置shared server必须的,而且只有这个参数是必须的。它指定了当实例启动的时候 shared server process 启动的数量,不要将这个参数设置得太大,否者启动数据库instance的时候就会花更多时间,ORACLE启动过后会根据负载来动态调整shared_servers
SQL> show parameter shared_server
NAME TYPE VALUE
------------------------------------ -------------------------------- ------------------------------
max_shared_servers integer 40
shared_server_sessions integer
shared_servers integer 1
SQL>
max_shared_servers:oracle在同一个时刻最大能够使用的shared server process.不要将这个参数设置小于shared_servers,如果动态修改shared_servers大于max_shared_servers,oracle会覆盖max_shared_servers的值,此时你需要修改max_shared_servers.同时也不能大于processes。这个参数是为了给占用很大资源操作而设的(批处理),为了预留一些process 给DBA任务(rman备份),
shared_server_sesions: 指定了总共允许的的shared server session 的数量。如果设置了这个参数,那么就不要将这个值超过sessions,如果没有设置这个值,那么只要还有空闲的session,就可以被使用。设置这个值是为专用连接预留的User Sessions.
3:通过lsnrctl services区分。
启用了共享服务器模式,可以通过调度器(dipatcher)的进程区分确认。
[oracle@DB-Server ~]$ lsnrctl services;
LSNRCTL for Linux: Version 10.2.0.4.0 - Production on 06-JAN-2015 23:46:30
Copyright (c) 1991, 2007, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.16.22)(PORT=1521)))
Services Summary...
Service "EPPS" has 2 instance(s).
Instance "EPPS", status UNKNOWN, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0
LOCAL SERVER
Instance "EPPS", status READY, has 8 handler(s) for this service...
Handler(s):
"D006" established:0 refused:0 current:0 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4336>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=10895))
"D005" established:0 refused:0 current:0 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4334>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=2469))
"D004" established:0 refused:0 current:0 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4332>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=13008))
"D003" established:0 refused:0 current:0 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4330>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=17578))
"D002" established:2 refused:0 current:1 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4328>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=44614))
"D001" established:2 refused:0 current:1 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4326>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=32323))
"D000" established:1 refused:0 current:1 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4324>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=22216))
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "EPPS_XPT" has 1 instance(s).
Instance "EPPS", status READY, has 8 handler(s) for this service...
Handler(s):
"D006" established:0 refused:0 current:0 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4336>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=10895))
"D005" established:0 refused:0 current:0 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4334>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=2469))
"D004" established:0 refused:0 current:0 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4332>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=13008))
"D003" established:0 refused:0 current:0 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4330>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=17578))
"D002" established:2 refused:0 current:1 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4328>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=44614))
"D001" established:2 refused:0 current:1 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4326>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=32323))
"D000" established:1 refused:0 current:1 max:1022 state:blocked
DISPATCHER <machine: nbooraclelnx01, pid: 4324>
(ADDRESS=(PROTOCOL=tcp)(HOST=DB-Server.localhost.localdomain)(PORT=22216))
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
没有启用共享服务器模式,则不会有调度器(dipatcher)的进程
[oracle@DB-Server ~]$ lsnrctl services;
LSNRCTL for Linux: Version 10.2.0.4.0 - Production on 06-JAN-2015 23:56:25
Copyright (c) 1991, 2007, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.16.22)(PORT=1521)))
Services Summary...
Service "EPPS" has 1 instance(s).
Instance "EPPS", status UNKNOWN, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0
LOCAL SERVER
The command completed successfully
其他一些不能完全确认的判断方式。
select * from v$shared_server; ---有记录,且STATUS字段为WAIT(COMMON),则说明启动共享;
---status为TERMINATED或者无记录,则说明没有启动共享服务器
select * from v$dispatcher; ---有无记录都不能说明启动共享服务器,只能说明是配置了dispatchers参数
select * from v$circuit ; ---有记录说明当前有使用共享模式的连接,无记录则不能判定服务器模式
关闭数据库共享模式
只需要将参数shared_servers设置为0,即可关闭数据库的共享模式。执行该脚本后,所有以共享方式连接到数据库都不能成功,但是未释放的共享连接会继续保持连接,直到断开为止。
alter system set shared_servers=0;
如果同时将参数shared_servers和max_shared_servers都设置为0,那么共享连接方式将被终结。所有的共享方式连接都会断开(已经连接的会话也会断开)
SQL> show parameter shared_servers
NAME TYPE VALUE
------------------------------------ -------------------------------- --------
max_shared_servers integer 40
shared_servers integer 4
SQL> alter system set shared_servers=0 scope=both;
System altered.
SQL> alter system set max_shared_servers=0 scope=both;
System altered.
开启数据库共享模式
默认情况下,数据库都是专用服务器模式,如何开启共享服务器模式呢? 一般只需要设置shared_servers这个参数,将其值设置为大于0即可开启服务器共享模式。其他的共享服务器参数可以不用设置,但是最好也设置一下max_shared_servers参数
SQL> alter system set shared_servers=1 scope=both;
System altered.
SQL> alter system set max_shared_servers =24 scope=both;
System altered.
但是在实际测试情况中发现,参数dispatchers也会影响到数据库开启共享服务器模式,如下所示,将参数dispatchers设置为空,shared_servers设置为1
SQL> show parameter shared
NAME TYPE VALUE
------------------------------------ -------------------------------- --------
hi_shared_memory_address integer 0
max_shared_servers integer 0
shared_memory_address integer 0
shared_pool_reserved_size big integer 26843545
shared_pool_size big integer 0
shared_server_sessions integer
shared_servers integer 0
SQL> alter system set dispatchers='' scope=both;
System altered.
SQL> alter system set shared_servers=1 scope=both;
System altered.
SQL>
此时以共享连接方式方式连接数据库会遭遇“ORA-12523: TNS: 监听程序无法找到适用于客户机连接的例程"错误。设置参数dispacthers后即可开启共享连接模式。如果参数dispacthers不为空,那么只要设置了参数shared_servers大于0即可。
SQL> alter system set dispatchers='(PROTOCOL=TCP)';
System altered.
结论:如果dispatches参数设置为空的话,不能启动共享服务器。
关于参数dispatchers的设置,可以使用下面命令
alter system set dispatchers='(protocol=TCP)(disp=8)(serv=xxx)’
前面表示的是协议,disp表示调度器(dipatcher)的进程数量,service分别指定要采用共享服务器模式的服务名称。使用上面的模式指定只启动某个服务的共享模式,如果要设置所有服务都使用共享模式,则设置为:
alter system set dispatchers='(PROTOCOL=TCP)';
如何判断某个会话采用的那种连接方式呢?
1:查看V$SESSION视图
SELECT SID, USERNAME, OSUSER, MACHINE,TERMINAL, SERVER FROM V$SESSION WHERE USERNAME IS NOT NULL;
COL USERNAME FOR A20
COL OSUSER FOR A10
COL MACHINE FOR A20
COL TERMINAL FOR A20;
SELECT SID, USERNAME, OSUSER, MACHINE,TERMINAL, SERVER
FROM V$SESSION
USERNAME为NULL表示的是数据库后台进程,
2:查看连接数据库的tns配置文件,如下所示
1:以共享服务器模式连接数据库
TEST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.16.22)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = SHARED)
(SERVICE_NAME = epps)
)
)
2:以专用服务器模式连接数据库
TEST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.16.22)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = epps)
)
)
TEST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.16.22)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = epps)
)
)
本文转载的是一位大神-萧湘隐者博客的一篇文章