在Oracle 11g中,提出了突破傳統專用/共享連接的第三種連接方式——Database Resident Connection Pooling(DRCP)。本篇我們一起來探討這項技術。
1、 從Dedicated Server到Shared Server
Oracle Client Process連接到Server Process的方式,傳統上有兩種方式:Dedicated Server和Shared Server。在Client連入到Oracle Server的過程中,默認是通過監聽器listener監聽器進行Oracle實例服務定位。只有再由監聽器fork出的子進程向Instance請求出一個Server Process與Client Process遠程通信。不同的連接方式,就體現在數據庫實例在接受到Server Process請求後,是怎麼樣提供出Server Process進程,以及該進程如何管理的。
Dedicated Server模式也稱爲專用連接方式,就是Oracle Instance會專門創建出一個新的Server Process與Client Process進行遠程通信。在整個Client Process請求過程中,Server Process只爲該Client提供服務。UGA信息也保存在Server Process的PGA空間中。當會話結束,Client連接中斷,Server Process就失去“存在意義”被清除掉,分配內存回收。Dedicated方式是我們最常使用的數據庫連接方式。在長會話或前端應用使用連接池組件的情況下,Dedicated方式的優勢是很明顯的。
與Dedicated Server模式對應的是Shared Server。在該模式下,Oracle實例會維持兩種Server Process:分發進程(Dispatcher DXXX)和共享進程(SXXX)。
SQL> select addr, pid, spid, username, program from v$process where program like '%000%';
ADDR PID SPID USERNAME PROGRAM
-------- ---------- ------------ --------------- --------------------
6D24BA1C 13 648 SYSTEM ORACLE.EXE (D000)
6D24C00C 14 1736 SYSTEM ORACLE.EXE (S000)
當監聽器向數據庫實例提出Server Process分配請求的時候,在Shared Server模式下,監聽器會向分發進程DXXX請求分配Server Process。DXXX會根據當前的空閒Server情況,分配出一個Server Process供使用。當Client使用結束之後,Server Process(SXXX)並不是被釋放,而是重新回到D000管制下。系統也會依據參數設置,維持一個穩定的SXXX數量。
SQL> show parameter shared_servers
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
max_shared_servers integer
shared_servers integer 1
Shared Server連接模式的出現,是和短會話、高併發的互聯網應用發展相關。每次創建和回收Server Process的成本是很高的。如果應用沒有中間層連接池,而是高併發的創建Server Process並且快速回收,這對於數據庫來說是很高的壓力。
從現在的應用設計開發看,連接池管理已經滲透入主流應用系統框架,shared server方式實際中應用不是很廣泛。
2、Database Resident Connection Pooling(DRCP)
如果我們站在軟件模式的角度看,Shared Server本質上也是想實現一種在數據庫層面上的連接池。這點在Oracle 11g上得到了實現,Oracle駐留連接池(DRCP)就是一個允許在多進程(Multi-Process)和多線程(Multi-Threads)之間共享連接的新特性。
Shared server在一定程度上緩解了Server process IDEL和頻繁創建銷燬Server process的問題。但是,Shared Server沒有解決Session數據共享的問題。當存在client需要長時間持有session,同時其他client沒有大量會話要求的時候,這種模型是有效的。但是,在每次請求會話的時間很短(短會話)和數據庫活動需要多次會話交互的時候,DRCP就是更加理想的連接池模型了。
DRCP新特性主要針對的就是應用程序在訪問數據庫時,出現高併發連接數問題。DRCP連接池將Server和Session信息進行緩存,爲多個訪問的應用程序提供連接共享。
同Shared Server一樣,DRCP前端存在一個代理(Connection Broker),負責應用中間件連接的共享要求,同時負責管理數據庫實例上的連接池連接。當應用中間件想Broker提出連接請求的時候,Broker會從連接池中找出空閒連接。當交互結束後,Server Process被釋放回連接池供重用。
同shared server不同的方面在於。當共享池中連接池被分配出之後,等價於dedicated server方式。
3、三種連接方式的內存使用情況
三種連接方式下,Oracle實例、Server Process和內存使用方式截然不同。
ü Dedicated Server方式
當Client Server請求連接的時候,全新的Server Process和session信息被創建。當連接中斷,Server Process和Session全部被釋放。內存分配是一個連接要分配Server Process和Session的空間。UGA信息是保存在PGA裏的。
ü Shared Server方式
當接收到Client Server的請求之後,Dispatcher會將請求放置在一個common隊列中。可用的Server Process就從隊列中獲取請求信息。當終止會話之後,對應的會話信息就被釋放掉。Session信息是從SGA中分配出。
ü DRCP方式
當Client Server請求之後,Connection Broker從連接池中尋找一個空閒Pooled Server提供給Client Server。如果沒有空閒的,Connection Broker就會創建出一個新的連接。如果當前連接池已經達到最大數量限制,就將請求放置在等待隊列中,等待空閒Server。
當釋放Pooled Server回到Connection Pool的時候,相應的數據庫資源被釋放掉。DRCP的內存要求與存儲池大小和會話有關。每個Pooled Server有一個Session信息,且存儲在PGA中。
下面一個分配實例,來說明情況:
場景:一個應用程序,其每個session需要400k的空間。每個Server process對應4M空間。連接池大小爲100,共享shared Server大小數據量也是100。如果有5000個連接數。
在Dedicated Server模式下:
Memory Usage=5000*(0.4M+4M)=22GB;
在Shared Server模式下:
Memory Usage=5000×0.4M+4M×100=2.5GB;注意,其中Session信息的2G是從SGA中分配的。
在DRCP模式下:
Memory Usage=100×(4M+0.4M)+5000×35K=615MB。注意:35K爲維護會話信息使用的內存大小。
4、結論
DRCP模式在傳統的shared server基礎上,爲前端應用提供更加成熟的數據連接池解決方案。從目前的資料看,DRCP對OCI、PHP等多種驅動提供了支持。注意:對JDBC Thin和JDBC OCI的支持還不存在。
1、Database Level Configuration
配置DRCP是分爲兩個步驟:database level configuration和application level configuration。首先在Database Server層面創建連接池對象。我們使用Oracle 11g進行試驗。
SQL> select * from v$version;
BANNER
---------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 – Production
在默認情況下,Oracle 11g中是有一個默認的連接池對象。在視圖dba_cpool_info中,可以看到連接池信息。
SQL> select connection_pool, status, minsize, maxsize, INACTIVITY_TIMEOUT from dba_cpool_info;
CONNECTION_POOL STATUS MINSIZE MAXSIZE INACTIVITY_TIMEOUT
------------------------------ ---------------- ---------- ---------- ------------------
SYS_DEFAULT_CONNECTION_POOL INACTIVE 4 40 300
連接池sys_default_connection_pool就是默認連接池,狀態是inactive。使用dbms_connection_pool包,可以方便的對其進行管理。
SQL> exec dbms_connection_pool.start_pool();
PL/SQL procedure successfully completed
使用start_pool方法,可以對默認池進行開啓。注意:該方法還有參數pool_name,如果指定了名稱,就可以創建出一個自定義的連接池,也可以同時管理多個連接池情況。如果不指定名稱,就針對默認連接池進行管理。
Start_pool之後,dba_cpool_info視圖中可以看到連接池狀態。
SQL> select connection_pool, status from dba_cpool_info;
CONNECTION_POOL STATUS MINSIZE
------------------------------ ---------------- ----------
SYS_DEFAULT_CONNECTION_POOL ACTIVE 4
注意,此時沒有連接,但是我們觀察後臺進程,發現新增加了連接池Server Process對象。
[oracle@oracle11g ~]$ ps -ef | grep ora_n
oracle 5800 1 1 05:07 ? 00:00:00 ora_n000_wilson
oracle 5816 5584 0 05:07 pts/0 00:00:00 grep ora_n
[oracle@oracle11g ~]$ ps -ef | grep ora_l
oracle 5689 1 0 05:03 ? 00:00:00 ora_lgwr_wilson
oracle 5802 1 0 05:07 ? 00:00:00 ora_l000_wilson
oracle 5804 1 0 05:07 ? 00:00:00 ora_l001_wilson
oracle 5806 1 0 05:07 ? 00:00:00 ora_l002_wilson
oracle 5808 1 0 05:07 ? 00:00:00 ora_l003_wilson
oracle 5818 5584 0 05:07 pts/0 00:00:00 grep ora_l
其中ora_n000進程是對應的Connection Broker對象,負責連接管理。Ora_lxxx進程就是連接池中的連接對象。當沒有連接的時候,連接池維持minsize大小,與配置minsize=4相匹配。
下面進行application level configuration。
2、Application Level Configuration
在應用層面,可以從連接字符串或者本地服務名上進行配置。本篇主要從本地服務名上進行配置。
在tnsnames.ora中,我們可以進行本地命名配置。爲了保證正確性,筆者傾向使用Oracle提供的netca工具來進行基礎配置。
--開啓X Windows Passive模式
[oracle@oracle11g ~]$ export DISPLAY=192.168.0.1:0.0
[oracle@oracle11g ~]$ netca
Oracle Net Services Configuration:
Default local naming configuration complete.
Created net service name: wilsondrcp
Oracle Net Services configuration successful. The exit code is 0
之後,修改tnsname.ora文件的相關內容。
WILSONDRCP =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.88)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = POOLED) --新增加到其中,表明連接使用連接池;
(SERVICE_NAME = wilson)
)
)
可以使用tnsping方法進行驗證。
[oracle@oracle11g ~]$ tnsping wilsondrcp
TNS Ping Utility for Linux: Version 11.2.0.1.0 - Production on 01-MAR-2012 05:10:46
Copyright (c) 1997, 2009, Oracle. All rights reserved.
Used parameter files:
/u01/oracle/network/admin/sqlnet.ora
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.88)(PORT = 1521))) (CONNECT_DATA = (SERVER = POOLED) (SERVICE_NAME = wilson)))
OK (0 msec)
配置了wilsondrcp名稱之後,就可以使用sqlplus等工具進行連接。
[oracle@oracle11g ~]$ sqlplus /nolog
SQL*Plus: Release 11.2.0.1.0 Production on Thu Mar 1 05:11:47 2012
Copyright (c) 1982, 2009, Oracle. All rights reserved.
SQL> conn scott/tiger@wilsondrcp
Connected.
SQL> select sid from v$mystat where rownum<2;
SID
----------
146
此時,會話(sid=146)已經連接。此時,我們可以查看後臺進程情況。
--標記LOCAL的本地連接進程不存在;
[oracle@oracle11g ~]$ ps -ef | grep LOCAL
oracle 5963 5931 0 05:14 pts/1 00:00:00 grep LOCAL
那麼,我們連接的會話進程究竟是哪一個呢?
SQL> select paddr from v$session where sid=146;
PADDR
--------
38BCD994
SQL> select pid, spid from v$process where addr='38BCD994';
PID SPID
---------- ------------------------
31 5806 –OS Level的進程編號;
[oracle@oracle11g ~]$ ps -ef | grep 5806
oracle 5806 1 0 05:07 ? 00:00:00 ora_l002_wilson
oracle 5975 5931 0 05:15 pts/1 00:00:00 grep 5806
對應的ora_l002_wilson進程就是我們剛剛看到的連接池進程。說明:我們使用sqlplus連接使用的連接池對象是通過DRCP。
在sqlplus退出之後,l002進程依然存在,只是被釋放回連接池。
SQL> quit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
[oracle@oracle11g ~]$ ps -ef | grep 5806
oracle 5806 1 0 05:07 ? 00:00:00 ora_l002_wilson
oracle 5981 5931 0 05:15 pts/1 00:00:00 grep 5806
[oracle@oracle11g ~]$
3、連接池關閉
DRCP連接池是可以關閉的,同樣使用dbms_connection_pool的stop_pool方法。
--關閉connection pool
SQL> exec dbms_connection_pool.stop_pool;
PL/SQL procedure successfully completed
[oracle@oracle11g ~]$ ps -ef | grep ora_n
oracle 5800 1 0 05:07 ? 00:00:00 ora_n000_wilson
oracle 6008 5931 0 05:18 pts/1 00:00:00 grep ora_n
[oracle@oracle11g ~]$ ps -ef | grep ora_l
oracle 5689 1 0 05:03 ? 00:00:00 ora_lgwr_wilson
oracle 6010 5931 0 05:18 pts/1 00:00:00 grep ora_l
關閉連接池後,連接池中連接lxxx立即被銷燬釋放。Connection Broker進程暫時存在。但是,過一會之後,該進程消失。
[oracle@oracle11g ~]$ ps -ef | grep ora_n
oracle 6027 5931 0 05:22 pts/1 00:00:00 grep ora_n
4、配置DRCP關鍵參數
在dba_cpool_info視圖中,我們可以查看到相應的參數信息。
SQL> desc dba_cpool_info;
Name Type Nullable Default Comments
---------------------- ------------- -------- ------- ------------------------------------------------------------
CONNECTION_POOL VARCHAR2(128) Y Connection pool name
STATUS VARCHAR2(16) Y connection pool status
MINSIZE NUMBER Y Minimum number of connections
MAXSIZE NUMBER Y Maximum number of connections
INCRSIZE NUMBER Y Increment number of connections
SESSION_CACHED_CURSORS NUMBER Y Session cached cursors
INACTIVITY_TIMEOUT NUMBER Y Timeout for an idle session
MAX_THINK_TIME NUMBER Y Max time for client to start activity on an acquired session
MAX_USE_SESSION NUMBER Y Maximum life of a session based on usage
MAX_LIFETIME_SESSION NUMBER Y Maximum life of a session based on time
NUM_CBROK NUMBER Y
MAXCONN_CBROK NUMBER Y
在DRCP連接池中,最常用的幾個參數是minsize、maxsize和inactivity_timeout。
Minsize是說明DRCP連接池初始連接進程數量,如果請求數量超過這個minsize值,就會進行自動拓展。每次進行拓展的進程個數是incrsize參數。
Maxsize表示DRCP最大的拓展進程數量。當已經達到這個數量之後,DRCP連接池就不會獲取到連接,被hange住。
DRCP對應的應用需求是“短會話、高併發”的應用場景。所以DRCP服務的連接必然是短時間交互。Inactivity_timeout參數就是設置這個timeout值。如果會話連接到這個連接之後,超過一定時間沒有inactive交互,Oracle會自動將其斷開。Server Process被釋放回連接池。
配置connection pool,我們可以使用dbms_connection_pool方法configure_pool。
SQL> exec dbms_connection_pool.configure_pool(minsize => 1,maxsize =>3,incrsize => 1,inactivity_timeout =>60);
PL/SQL procedure successfully completed
SQL> select connection_pool, status, minsize, maxsize, INACTIVITY_TIMEOUT from dba_cpool_info;
CONNECTION_POOL STATUS MINSIZE MAXSIZE INACTIVITY_TIMEOUT
------------------------------ ------- --------- ---------- ------------------
SYS_DEFAULT_CONNECTION_POOL INACTIVE 1 3 60
--啓動連接池;
SQL> exec dbms_connection_pool.start_pool;
PL/SQL procedure successfully completed
--後臺進程情況;
[oracle@oracle11g ~]$ ps -ef | grep ora_n
oracle 6035 1 3 05:22 ? 00:00:00 ora_n000_wilson
oracle 6039 5931 0 05:23 pts/1 00:00:00 grep ora_n
[oracle@oracle11g ~]$ ps -ef | grep ora_l
oracle 5689 1 0 05:02 ? 00:00:00 ora_lgwr_wilson
oracle 6037 1 0 05:22 ? 00:00:00 ora_l000_wilson
oracle 6041 5931 0 05:23 pts/1 00:00:00 grep ora_l
5、maxsize值突破實驗
我們實驗一下,當突破maxsize值的時候,會出現什麼現象。我們啓用sqlplus連接。
--第一會話
SQL> conn scott/tiger@wilsondrcp
Connected.
SQL> set time on;
05:23:45 SQL> select sid from v$mystat where rownum<2;
SID
----------
14
--第二會話
SQL> conn scott/tiger@wilsondrcp
Connected.
SQL> set time on
05:24:26 SQL> select sid from v$mystat where rownum<2;
SID
----------
22
啓動了兩個連接,此時連接池進程情況如下:
[oracle@oracle11g ~]$ ps -ef | grep ora_l
oracle 5689 1 0 05:03 ? 00:00:00 ora_lgwr_wilson
oracle 6037 1 0 05:22 ? 00:00:00 ora_l000_wilson
oracle 6052 1 0 05:23 ? 00:00:00 ora_l001_wilson
oracle 6054 1 0 05:23 ? 00:00:00 ora_l002_wilson
oracle 6118 5931 0 05:24 pts/1 00:00:00 grep ora_l
拓展到三個連接進程。但是,此時如果我們進行第三個連接連入,就不允許了。
SQL*Plus: Release 11.2.0.1.0 Production on Thu Mar 1 05:25:16 2012
Copyright (c) 1982, 2009, Oracle. All rights reserved.
SQL> conn scott/tiger@wilsondrcp
(數據庫連接動作hange住)
這裏,我們需要注意一個細節:連接池中存在三個server process,但是爲什麼第三個連接不能連入。注意:在DRCP連接池中,Oracle是要保留一個連接作爲身份權限驗證等操作使用的。不能將其分配出去。Maxsize我們設置爲3,所以自然沒有連接。
第三個連接hange住一段時間後,自動連入。
Connected.
SQL> select sid from v$mystat where rownum<2;
SID
----------
14
第三個會話連入。此時第一個和第二個會話是被強制斷開。
--第一會話
05:24:37 SQL> select sid from v$mystat where rownum<2;
select sid from v$mystat where rownum<2
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 6052
Session ID: 14 Serial number: 5
--第二會話
05:24:47 SQL> select sid from v$mystat where rownum<2;
select sid from v$mystat where rownum<2
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 6054
Session ID: 22 Serial number: 17
此時,後臺進程狀態有釋放連接。
[oracle@oracle11g ~]$ ps -ef | grep ora_l
oracle 5689 1 0 05:03 ? 00:00:00 ora_lgwr_wilson
oracle 6037 1 0 05:22 ? 00:00:00 ora_l000_wilson
oracle 6052 1 0 05:23 ? 00:00:00 ora_l001_wilson
oracle 6202 5931 0 05:28 pts/1 00:00:00 grep ora_l
附帶,dbms_connection_pool的restore_defaults方法,可以將設置值置回。
SQL> exec dbms_connection_pool.stop_pool;
PL/SQL procedure successfully completed
SQL> select connection_pool, status, minsize, maxsize, INACTIVITY_TIMEOUT from dba_cpool_info;
CONNECTION_POOL STATUS MINSIZE MAXSIZE INACTIVITY_TIMEOUT
------------------------------ ---------------- ---------- ---------- ------------------
SYS_DEFAULT_CONNECTION_POOL INACTIVE 1 3 60
SQL> exec dbms_connection_pool.restore_defaults;
PL/SQL procedure successfully completed
SQL> select connection_pool, status, minsize, maxsize, INACTIVITY_TIMEOUT from dba_cpool_info;
CONNECTION_POOL STATUS MINSIZE MAXSIZE INACTIVITY_TIMEOUT
------------------------------ ---------------- ---------- ---------- ------------------
SYS_DEFAULT_CONNECTION_POOL INACTIVE 4 40 300
6、結論
DRCP是Oracle 11g中的新特性。藉助DRCP,一些高併發、短會話應用可以獲得數據庫層面的高效連接池。筆者猜測Shared Server模式就是DRCP的一種早期雛形。在現代企業級應用系統中,連接池是中間件的一個重要組件。當一些應用,如PHP不能提供有效連接池的時候,DRCP也許是不錯的選擇。
轉載自:
http://blog.itpub.net/17203031/viewspace-717634/
http://blog.itpub.net/17203031/viewspace-717754/
http://blog.itpub.net/17203031/viewspace-717887/
感謝原作者!