Oracle 採用 **PMON 進程主動向監聽器註冊** 機制 (Dynamic Service Registration);
PROCESSES (實例進程上限, 含前台/後台)
│
├── SESSIONS = (1.1 * PROCESSES) + 5 (用戶會話上限)
│ │
│ └── TRANSACTIONS = 1.1 * SESSIONS (事務槽上限)
│
├── 受限於 OS 信號量: semmns ≥ PROCESSES + 額外
│
└── 受限於 OS 文件句柄: nofile ≥ SESSIONS * 2 (含網絡/文件)
-- 1. 當前進程數
SELECT COUNT(*) AS current_processes FROM v$process;
-- 2. 參數上限
SELECT name, value FROM v$parameter WHERE name IN ('processes','sessions','transactions');
-- 3. 當前會話數
SELECT COUNT(*) AS current_sessions FROM v$session WHERE type != 'BACKGROUND';
-- 4. 歷史峰值 (實例啟動以來)
SELECT * FROM v$resource_limit WHERE resource_name IN ('processes','sessions','transactions');
判斷邏輯**:若 `current_processes ≥ processes` 或 `current_sessions ≥ sessions` → **資源耗盡**,需擴容參數。
-- 按機器/用戶/程序統計連接數
SELECT machine, program, username, COUNT(*) cnt
FROM v$session
WHERE type != 'BACKGROUND'
GROUP BY machine, program, username
ORDER BY cnt DESC;
-- 找出長時間閒置會話 (潛在連接泄漏)
SELECT sid, serial#, username, machine, program, logon_time, last_call_et/60 idle_min
FROM v$session
WHERE type != 'BACKGROUND' AND last_call_et > 3600 -- 閒置超 1 小時
ORDER BY last_call_et DESC;
-- 找出阻塞鏈頭會話
SELECT blocking_session, sid, serial#, username, sql_id, event, seconds_in_wait
FROM v$session
WHERE blocking_session IS NOT NULL;
# 1. 服務狀態與處理器詳情
lsnrctl services LISTENER_NAME
# 關鍵輸出解讀:
# "Service "ORCL" has 1 instance(s)."
# "Instance "ORCL", status READY, has 2 handler(s) for this service..."
# "Handler(s):"
# "DEDICATED SERVER established:123 refused:0 state:ready" -- 專用服務器
# "DISPATCHER established:45 refused:0 state:ready" -- 共享服務器
# 若 state: BLOCKED → 實例負載已滿
# 2. 監聽器日志分析 (若啟用 log_status=on)
grep -i "12519\|12516\|BLOCKED\|established\|refused" $ORACLE_HOME/network/log/listener.log
# 1. 信號量 (semmns) - 每個 Oracle 進程佔用 1 個信號量
ipcs -ls | grep "semmns"
# 輸出: semmns = 32000 → 支持進程數 ≤ 32000
# 若 PROCESSES=3000,需 semmns ≥ 3000 + 其他進程
# 2. 文件句柄 (nofile) - oracle 用戶限制
ulimit -n # 查看當前 Shell 限制
cat /etc/security/limits.conf | grep oracle
# oracle soft nofile 65535
# oracle hard nofile 65535
# 3. 共享內存段 (shmmax, shmall) - SGA 大小限制
ipcs -lm | grep "max seg size"
# 需 ≥ SGA_TARGET/MEMORY_TARGET
# 4. 當前 Oracle 進程佔用信號量
ipcs -sp | grep oracle | wc -l
-- 1. 修改 PROCESSES (核心參數)
ALTER SYSTEM SET processes = 3000 SCOPE = SPFILE; -- 根據業務峰值預留 30%-50% 緩衝
-- 2. 同步調整 SESSIONS (可選,通常由公式自動推導)
-- ALTER SYSTEM SET sessions = 3305 SCOPE = SPFILE; -- (1.1*3000+5)
-- 3. 重啟實例生效
SHUTDOWN IMMEDIATE;
STARTUP;
-- 4. 驗證
SHOW PARAMETER processes;
SELECT * FROM v$resource_limit WHERE resource_name = 'processes';
# 1. 從內存創建 PFILE
$ sqlplus / as sysdba
SQL> CREATE PFILE='/tmp/initORCL.ora' FROM SPFILE; -- 或 FROM MEMORY
# 2. 編輯 PFILE 增加 processes=3000
# 3. 關閉實例,啟動到 NOMOUNT,創建 SPFILE,再 OPEN
SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP NOMOUNT PFILE='/tmp/initORCL.ora';
SQL> CREATE SPFILE FROM PFILE='/tmp/initORCL.ora';
SQL> STARTUP;
# /etc/sysctl.conf 追加
# Oracle 進程數 3000 + 系統預留
kernel.sem = 250 32000 100 128 # semmsl semmns semopm semmni
# semmns (32000) ≥ processes (3000) + 系統其他
# 文件句柄
fs.file-max = 6815744
# /etc/security/limits.conf
oracle soft nofile 65535
oracle hard nofile 65535
oracle soft nproc 16384
oracle hard nproc 16384
若使用 `DISPATCHERS` 共享服務器架構,還需檢查:
| 連接池參數 | 推薦配置 | 說明 |
|---|---|---|
| Min Pool Size | 5-10 | 預熱連接,避免冷啟動延遲 |
| Max Pool Size | 50-200 (視應用實例數) | **總和 ≤ DB SESSIONS * 0.7**,預留 30% 給後台/管理/突發 |
| Connection Lifetime | 120-300 秒 | 定期回收連接,防止防火牆斷開/DB 重啟導致失效連接殘留 |
| Connection Timeout | 15-30 秒 | 獲取連接超時,避免線程長時間阻塞 |
| Validate Connection | true | 從池獲取時執行 `SELECT 1 FROM DUAL` 驗證有效性 |
| Statement Cache Size | 50-200 | 客戶端語句緩存,減少解析開銷 (對應 `SESSION_CACHED_CURSORS`) |
-- 1. 識別並殺掉長時間閒置/無用會話 (謹慎執行,確認業務無影響)
DECLARE
CURSOR c_idle IS
SELECT sid, serial#, username, machine, program, last_call_et
FROM v$session
WHERE type != 'BACKGROUND'
AND username NOT IN ('SYS','SYSTEM','DBSNMP','SYSMAN') -- 保護系統用戶
AND last_call_et > 7200 -- 閒置超 2 小時
AND status = 'INACTIVE';
BEGIN
FOR s IN c_idle LOOP
BEGIN
EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION ''' || s.sid || ',' || s.serial# || ''' IMMEDIATE';
DBMS_OUTPUT.PUT_LINE('Killed: ' || s.sid || ',' || s.serial# || ' ' || s.username || '@' || s.machine);
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Failed: ' || s.sid || ',' || s.serial# || ' ' || SQLERRM);
END;
END LOOP;
END;
/
-- 2. 臨時調大 SESSIONS (無需重啟,但受 PROCESSES 硬限制)
-- 僅當 current_sessions 接近 sessions 但 processes 尚有餘裕時有效
ALTER SYSTEM SET sessions = 4000 SCOPE = MEMORY; -- 臨時生效,重啟失效
| 指標 | 來源 | 告警閾值 | 收集頻率 |
|---|---|---|---|
| Session Utilization % | `v$resource_limit` / `v$license` | > 75% Warning, > 90% Critical | 1 分鐘 |
| Process Utilization % | `v$resource_limit` | > 75% Warning, > 90% Critical | 1 分鐘 |
| Listener Refused Count | `lsnrctl services` / `listener.log` | > 0 (任何拒絕即告警) | 實時/5 分鐘 |
| Idle Session Count (>1h) | `v$session` | > 10% 總會話數 | 5 分鐘 |
| Blocked Session Count | `v$session` (blocking_session IS NOT NULL) | > 0 | 1 分鐘 |
| OS Semaphore Usage % | `ipcs -ls` / `ipcs -sp` | > 80% | 5 分鐘 |