oracle在11g中引入了database resident connection pooling(DRCP)。在此之前,我们可以使用dedicated 或者share 方式来链接数据库,dedicated方式是oracle数据库默认的链接方式,无需过多的配置,而且关于dedicated的bug也是非常少的,因此,通常情况下,建议使用dedicated方式来链接数据库。但是,在服务器资源有限,并且同时连接数据库的用户量非常大时,dedicated方式就无能为力了。假设并发用户为5000,每个dedicated进程需要包含4m的内存,而每个sessioin占用的内存量为400k,那么我们总共需要21.43g的内存。这时我们可以采用share方式来连接数据库,假设共享服务进程数量为100,则总共需要2.29g的内存,其中2g的内存分配自sga。但是shared连接方式由于存在过多的bug,而且为了使用shared方式,需要进行某些配置工作,因此,并不是我们希望采用的数据库连接方式。
在web横行的今天,数据库技术也面临着的前所未有的挑战。熟悉web技术的人员都知道,web是一种无状态技术。用户请求网页,服务器处理用请求,连接数据库获取数据并进行处理,断开数据库连接,展现网页至用户,这是一般网页的处理流程,它具有数据库连接时间短、频繁连接数据库、并发量大的特点。此时,人们引入了连接池技术,但是这些技术多数是在客户端层面或者中间件层面实现的,具有如下缺陷“
1.连接池多是单个独立的节点,如果多个节点需要使用公用的数据库连接,往往需要在各个节点独自配置,这无疑会浪费数据库资源
2.连接池多数采用预分配的方式连接数据库,因此在用户压力不大的情况下,同样会持续保持数据库连接,进而浪费了数据库资源
除此之外,在某些多进程,单线程的环境(如php)下,使用连接池技术基本是不可能的。
DRCP的引入可以有效的解决这些问题,DRCP将session和服务器进程捆绑在一起进行缓存(pool server),用户请求连接数据库时,首先会连接到CONNECTION BROKER进程,broker进程根据连接信息从连接池中选择pool server,将其分配给请求用户,此后,用户直接和pool server通信,broker不再参与其中,直至用户断开连接,将pool server归还给连接池。
同样假设并发用户数量为5000,pool server为100,DRCP所需内存为100 X (400 KB + 4 MB) + (5000 X 35KB)= 609.9 MB,其中(5000*35k)为broker内存,如图:
在11g中,已经预先安装了DRCP,但默认情况下,并没有启用。启用DRCP需要运行如下过程:
exec dbms_connection_pool.start_pool;
通过DBA_CPOOL_INFO视图可以查看DRCP的启用状态。
SQL> select connection_pool,status from dba_cpool_info; CONNECTION_POOL STATUS
------------------------------ ------------------------------------------------
SYS_DEFAULT_CONNECTION_POOL INACTIVE SQL> exec dbms_connection_pool.start_pool; PL/SQL 过程已成功完成。 SQL> select connection_pool,status from dba_cpool_info; CONNECTION_POOL STATUS
------------------------------ ------------------------------------------------
SYS_DEFAULT_CONNECTION_POOL ACTIVE
为了使用DRCP,我们需要在客户端进行一些配置,如果客户端使用的是tnsname.ora 文件,我们需要将(server=POOLED)添加到CONNECT_DATA段中,如:
ORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = ROBERTSDELLXPS)(PORT = 1521))
(CONNECT_DATA =
(SERVER = POOLED)
(SERVICE_NAME = orcl)
)
)
如果采用EASYCONNECTION方式连接数据库,则需要保证连接字符串为如下格式:
sqlplus scott/tiger@easy:1521/orcl:pooled
适用场景
内存资源有限情况下,需要支持大量用户连接
客户端用户具有相似性,并可重用或者共享session。(相似性:以相同的数据库凭证登录数据库,并且使用相同的用户schema)
用户连接具有短暂性.
不存在跨客户端session.
客户端是多进程或者多主机.
RDCP的限制
如果在链接池中有活动的用户,则如下操作是无法完成的
关闭数据库(数据库hang住,直至所有的pool session结束)
停止RCDP (当前执行stop_pool的session hang住)
更改pool session的用户密码(本人测试是可以修改的,不知是我测试的有问题还是官方文档错误,有知道的高手,请赐教)
Use shared database links to connect to a database resident connection pool
使用高级安全选项,如加密等
利用OCI_MIGRATE或者 OCIConnectionPool实现可迁移的session
DDL statements that pertain to database users in the pool need to be performed carefully, as the pre-DDL sessions in the pool can still be given to clients post-DDL. For example, while dropping users, ensure that there are no sessions of that user in the pool and no connections to the Broker that were authenticated as that user.
Sessions with explicit roles enabled, that are released to the pool, can be later handed out to connections (of the same user) that need the default logon role. Avoid releasing sessions with explicit roles, and instead terminate them
Connection Classes
默认情况下,DRCP会保证不同用户之间是不可以共享连接的。这种保证是通过CONNECTION CLASSES来实现的,每个连接对应一个connection classes,只有cc相同的连接才可以共享,默认情况下,cc为“usernmae.shared”例如“EASY.SHARED”。除此之外,我们也可以通过客户端的连接请求,来手工指定connection classes ,从而达到相同的用户连接之间的细粒度划分。
SESSION PURITY
通过在客户端指定PURITY参数,可以影响客户端请求连接时的行为,如果purity=new,则连接池会新建练级,如果purigy=self,则会重用已有连接。
有个PURITY 和connection classes在oci部分由比较详细的描述。如下是JDBC设置CONNECTION CALSSES 的示例:
String url = "jdbc:oracle:thin:@//localhost:5521/orcl:POOLED";
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();
pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
// Set DataSource Property
pds.setUser("HR");
pds.setPassword("hr");
System.out.println ("Connecting to " + url);
pds.setURL(url);
pds.setConnectionPoolName("HR-Pool1");
pds.setMinPoolSize(2);
pds.setMaxPoolSize(3);
pds.setInitialPoolSize(2);
Properties prop = new Properties();
prop.put("oracle.jdbc.DRCPConnectionClass", "HR-Pool1");
pds.setConnectionProperties(prop);
相关PLSQL包
我们可以通过如下PLSQL包来管理DRCP:
SQL> desc dbms_connection_pool
PROCEDURE ALTER_PARAM
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
POOL_NAME VARCHAR2 IN DEFAULT
PARAM_NAME VARCHAR2 IN
PARAM_VALUE VARCHAR2 IN
PROCEDURE CONFIGURE_POOL
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
POOL_NAME VARCHAR2 IN DEFAULT
MINSIZE BINARY_INTEGER IN DEFAULT
MAXSIZE BINARY_INTEGER IN DEFAULT
INCRSIZE BINARY_INTEGER IN DEFAULT
SESSION_CACHED_CURSORS BINARY_INTEGER IN DEFAULT
INACTIVITY_TIMEOUT BINARY_INTEGER IN DEFAULT
MAX_THINK_TIME BINARY_INTEGER IN DEFAULT
MAX_USE_SESSION BINARY_INTEGER IN DEFAULT
MAX_LIFETIME_SESSION BINARY_INTEGER IN DEFAULT
PROCEDURE RESTORE_DEFAULTS
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
POOL_NAME VARCHAR2 IN DEFAULT
PROCEDURE START_POOL
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
POOL_NAME VARCHAR2 IN DEFAULT
PROCEDURE STOP_POOL
参数名称 类型 输入/输出默认值?
------------------------------ ----------------------- ------ --------
POOL_NAME VARCHAR2 IN DEFAULT
相关视图
DBA_CPOOL_INFO
提供与连接池相关的信息,如状态(活动,非活动)和各种属性(最小值,最大值等)
SQL> SELECT connection_pool, status, maxsize FROM dba_cpool_info; CONNECTION_POOL STATUS MAXSIZE
------------------------------ ---------------- ----------
SYS_DEFAULT_CONNECTION_POOL INACTIVE 40
V$CPOOL_STATS
提供有关连接池的统计信息
SQL> SELECT pool_name, num_requests, num_hits, num_misses
2* FROM v$cpool_stats; POOL_NAME NUM_REQUESTS NUM_HITS NUM_MISSES
---------------------------- ------------ ---------- ----------
SYS_DEFAULT_CONNECTION_POOL 1 0 1
V$CPOOL_CC_INFO
提供连接池与连接类别(connection class)之间的对应关系
SQL> SELECT * FROM v$cpool_cc_info; POOL_NAME CCLASS_NAME
---------------------------- --------------
SYS_DEFAULT_CONNECTION_POOL SCOTT.SHARED
V$CPOOL_CC_STATS
提供连接类别(connection class)的统计信息
SQL> SELECT cclass_name, num_requests, num_hits, num_misses
2* FROM v$cpool_cc_stats; CCLASS_NAME NUM_REQUESTS NUM_HITS NUM_MISSES
-------------------- ------------ ---------- ----------
SCOTT.SHARED 1 0 1
DRCP相关进程