前言
Oracle 客戶端連線資料庫有兩種根本不同的架構:專用伺服器與共用伺服器。理解其運作機制、記憶體模型與 TCP/IP 連線流程,是效能調校與架構設計的基石。
一、專用伺服器
架構特徵
- 客戶端連線時,Oracle **建立新進程 (UNIX) / 新執行緒 (Windows)**
- 該進程/執行緒**專屬服務單一 Session**,生命週期綁定
- **一對一映射**:N 個 Session = N 個專用伺服器進程
- **非實例一部分**:不屬於背景進程集合 (SMON, PMON, DBWn...)
- 客戶進程透過 **TCP/IP Socket 直接通訊**
連線路徑
Client Process → TCP/IP → Dedicated Server Process → (Memory Access) → SGA → Instance → Database
UNIX vs Windows 實作差異
| 層面 | UNIX/Linux | Windows |
| 建立機制 | Listener `fork()` + `exec()` 新進程 | Listener 請求資料庫進程建立新執行緒 |
| 記憶體模型 | 進程私有 PGA,透過 `shmat()` 附掛 SGA 共享記憶體段 | 單一進程多執行緒,共享虛擬記憶體空間 (SGA 在同一位址空間) |
| 客戶重導向 | 新進程繼承 Listener Socket,直接通訊 | 客戶「重導向」至新執行緒建立物理連線 |
優缺點
| 優點 | 缺點 |
| 隔離性強,單一 Session 故障不影響他人 | 高並發時進程/執行緒數暴增,OS 切換開銷大 |
| 程式模型簡單,除錯容易 | 記憶體佔用高 (每進程獨立 PGA + UGA) |
| 適合長連線、複雜操作、批次作業 | 不適合大量短連線 (Web 應用) |
二、共用伺服器
架構特徵 (原稱 MTS - Multi-Threaded Server)
- **連線池機制**:固定數量的共用伺服器進程服務大量 Session
- **調度器** 接收客戶請求,放入 **SGA 請求佇列**
- 空閒共用伺服器從佇列取出請求處理,結果放入 **回應佇列**
- 調度器取回應傳回客戶
- 共用伺服器隨實例啟動,非按需建立
連線流程
Client → Dispatcher → SGA (Request Queue) → Shared Server → SGA (Response Queue) → Dispatcher → Client
關鍵差異:通訊中介
| 專用伺服器 | 共用伺服器 |
| 客戶進程 **直接** 與專用伺服器通訊 | 客戶進程 **不直接** 與共用伺服器通訊 |
| 無中介進程 | **調度器** 為必經中介 |
優缺點
| 優點 | 缺點 |
| 大幅減少進程/執行緒數 (支援萬級連線) | 單一共用伺服器故障影響多 Session |
| 記憶體效率高 (UGA 在 SGA Large Pool 共享) | 長耗時操作 (大排序、大查詢) 佔用共用伺服器久 |
| 適合 Web 應用、連線池、大量短連線 | 部分功能受限 (如某些 PL/SQL、DB Link 行為) |
三、TCP/IP 連線建立完整流程
客戶端發起
sqlplus scott/tiger@ora10g.localdomain
scott/tiger:用戶名/密碼
ora10g.localdomain:**TNS 服務名** (Transparent Network Substrate)
TNS 解析
- 客戶端讀取
tnsnames.ora (通常在 $ORACLE_HOME/network/admin/)
- 解析服務名 → 主機名、埠號 (預設 1521)、服務名/ SID
- 或透過 **OID (Oracle Internet Directory / LDAP)** 解析
伺服器端 Listener 處理
┌─────────────────────────────────────────────────────────────┐
│ Listener Process (Port 1521) │
│ 接收連線請求 → 檢查 listner.ora / 動態註冊資訊 │
│ │ │
│ ├─ 專用伺服器請求 → fork()/建立執行緒 → 專用伺服器繼承 Socket
│ │ │
│ └─ 共用伺服器請求 → 從調度器池選擇一個 → 回傳調度器連線資訊
│ │ │
│ ▼ ▼
│ 客戶斷開 Listener 客戶直接連調度器
│ 與專用伺服器通訊 建立物理連線
└─────────────────────────────────────────────────────────────┘
UNIX 專用伺服器建立細節
Listener 接收連線
│
├─ fork() → 子進程 (複製父進程記憶體映像)
│
├─ exec() → 替換為 Oracle 專用伺服器程式映像
│
└─ 子進程繼承 Listener 建立的 Socket 檔案描述符
→ 直接與客戶通訊,存取 SGA (shmat)
Windows 專用伺服器建立細節
Listener (單一進程多執行緒)
│
├─ 請求資料庫主進程建立新執行緒
│
└─ 客戶「重導向」至新執行緒
→ 共享同一虛擬記憶體空間 (SGA 自然可見)
四、選型決策指南
| 場景 | 推薦模式 | 關鍵參數設定 |
| 傳統 Client/Server、批次作業、長連線 | 專用伺服器 | 無特殊設定 (預設) |
| Web 應用、連線池、大量短連線 | 共用伺服器 | DISPATCHERS, SHARED_SERVERS, MAX_SHARED_SERVERS |
| 混合負載 | 混合模式 | 兩種服務名分別指向不同模式 |
| RAC 環境 | 視負載而定 | SCAN Listener + 服務屬性控制 |
五、監控與診斷
-- 專用伺服器進程數
SELECT COUNT(*) FROM v$process WHERE background = 'NO' AND paddr != (SELECT paddr FROM v$process WHERE program LIKE '%PMON%');
-- 共用伺服器統計
SELECT * FROM v$shared_server;
SELECT * FROM v$dispatcher;
SELECT * FROM v$queue; -- 請求/回應佇列等待
-- 當前連線模式
SELECT s.sid, s.serial#, s.username, s.server, s.machine
FROM v$session s
WHERE s.type = 'USER';
結語
專用伺服器以**隔離性**換取簡單性,共用伺服器以**共享性**換取擴展性。TCP/IP 連線建立中,Listener 扮演「紅娘」角色,根據請求類型安排專用或共用伺服器。選型無絕對優劣,關鍵在於:**負載特徵 (連線數/持續時間/操作複雜度) 與硬體資源 (CPU/記憶體/OS 進程上限) 的匹配**。現代雲原生架構下,結合連線池 (UCP/HikariCP) + 專用伺服器,或 Database Resident Connection Pool (DRCP),往往能取得更佳平衡。