連接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)
)
)
參考資料:
http://blog.csdn.net/tianlesoftware/article/details/5695784
http://wenku.baidu.com/view/9b0f7f8a84868762caaed57c.html
http://www.itpub.net/thread-1714191-1-1.html