天天看點

oracle專用伺服器模式和共享伺服器模式詳解

  連接配接ORACLE伺服器一般有兩種方式:專用伺服器連接配接(dedicated server)和共享伺服器連接配接(shared server)。那麼兩者有啥差別和不同呢?下面我們将對這兩者的差別與不同一一剖析。

專用伺服器模式(dedicated server)

    在專用伺服器模式中,使用者程序運作在用戶端的機器上,專用伺服器程序運作在資料庫伺服器,使用者程序和專用伺服器程序是兩種不同類型的程序。

    對于專用伺服器模式,在使用者登入時,ORACLE總會建立一個新的服務程序,這通常稱為專用伺服器配置。這個伺服器程序會在會話生存期中專門為這個連接配接服務。對于每一個會話,都會生成一個新的專用伺服器程序,會話與專用伺服器程序之間存在一對一的映射關系。按照定義,這個專用伺服器不是執行個體的一部分。使用者程序(也就是想要連接配接資料庫的程式)會通過某種網絡通道(如TCP/IP Socket)與這個專用伺服器程序直接通信,并由這個伺服器程序接收和執行使用者程序送出的SQL。使用者程序與專用伺服器程序是一一對應關系。預設使用專用模式

oracle專用伺服器模式和共享伺服器模式詳解

專用伺服器模式(dedicated server)的一個很重要的特點就是UGA(使用者全局域)是存儲在PGA(程序全局域)中的,這個特性也很好說明了目前使用者的記憶體空間是按照程序來進行配置設定的。

專用伺服器模式适用場景:

1:隻有少量的用戶端連接配接系統或資料倉庫系統。資料集市系統等

2:聯機事務處理系統(OLTP)。當然聯機事務處理系統必須要符合下面兩個條件

    A 使用者連接配接請求數大于共享程序

    B 事務大部分是長事務或者大事務

共享伺服器模式(shared server)

    共享伺服器(shared server),正式的說法是多線程伺服器(Multi-Threaded Server)或MTS。如果采用這種連接配接方式,就不會對每條使用者連接配接建立另外的線程或新的程序。在連接配接建立的時候,Listener首先接收到用戶端的建立連接配接的請求,然後Listener去生成一個叫做排程器(dipatcher)的程序與用戶端進行連接配接。排程器把把用戶端的請求放在SGA(系統全局域)的一個請求隊列中,然後在共享伺服器連接配接池中查找有無空閑的連接配接,然後讓這個空閑的伺服器程序進行處理。處理完畢以後再把處理結果傳回給使用者。共享伺服器模式的請求流程如下所示

oracle專用伺服器模式和共享伺服器模式詳解

利用共享伺服器,我們不必為10,000 個資料庫會話建立10,000 個專用伺服器(這樣程序或線程就太多了),而隻需建立很少的一部分程序/線程,顧名思義,這些程序/線程将由所有會話共享。這樣Oracle 就能讓更多的使用者與資料庫連接配接,否則很難連接配接更多使用者。如果讓我的機器管理10,000個程序,這個負載肯定會把它壓垮,但是管理100 個或者1,000 個程序還是可以的。采用共享伺服器模式,共享程序通常與資料庫一同啟動,使用ps指令可以看到這個程序。

                  資料庫連接配接概述

oracle專用伺服器模式和共享伺服器模式詳解

共享伺服器模式缺點:

采用專用伺服器連接配接模式比采用共享伺服器連接配接模式效率要高。因為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;      
oracle專用伺服器模式和共享伺服器模式詳解

如果同時将參數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>      
oracle專用伺服器模式和共享伺服器模式詳解

此時以共享連接配接方式方式連接配接資料庫會遭遇“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)';      

如何判斷某個會話采用的那種連接配接方式呢?

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)      
    )      
  )      
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)      
    )      
  )