本文著重 **阻塞排查與手動干預**;死鎖由 Oracle 自動處理,僅需分析 Trace 文件 (`USER_DUMP_DEST`) 找出根因 SQL。
SELECT * FROM v$db_object_cache
WHERE owner = 'SCHEMA_NAME' AND locks != '0';
SELECT * FROM v$access
WHERE owner = 'SCHEMA_NAME' AND object = 'OBJECT_NAME_FROM_STEP1';
SELECT sid, serial#, paddr FROM v$session WHERE sid = ;
SELECT spid FROM v$process WHERE addr = ;
-- 4.1 資料庫層面優雅終結 (觸發回滾)
ALTER SYSTEM KILL SESSION ',';
-- 4.2 若標記為 KILLED 但未釋放 (長回滾),OS 層面強制殺進程
-- Linux/Unix:
kill -9
-- Windows (需 Oracle 安裝目錄 bin 下的 orakill.exe):
orakill
-- 一條 SQL 直接拿到所有關鍵資訊
SELECT
s.username,
lo.object_id,
lo.session_id AS sid,
s.serial#,
lo.oracle_username,
lo.os_user_name,
lo.process AS os_pid
FROM v$locked_object lo
JOIN v$session s ON lo.session_id = s.sid
WHERE s.username IS NOT NULL;
輸出即含 `SID, SERIAL#, OS_PID`,直接套用上述 `KILL SESSION` / `kill -9`。
SELECT
blocking.sid AS blocker_sid,
blocked.sid AS blocked_sid,
blocking.sql_id AS blocker_sql_id,
blocked.sql_id AS blocked_sql_id,
blocking.module AS blocker_module,
blocked.module AS blocked_module
FROM v$session blocking
JOIN v$session blocked ON blocking.sid = blocking.sid
WHERE blocking.blocking_session = blocked.sid; -- 11g+ 欄位
TX - Row Exclusive (TX) 互相等待 → 應用邏輯更新順序不一致導致。| 誤區 | 正確做法 |
|---|---|
| 直接 `kill -9` OS 進程 | 優先 `ALTER SYSTEM KILL SESSION` 讓 PMON 協調回滾,僅在卡住時用 OS kill |
| 以為死鎖就是阻塞 | 死鎖 Oracle 自動解決;阻塞需人工干預或等待超時 |
| 只看 v$session 忽略 v$process | OS 層面殺進程需 SPID,必須關聯 v$process |
| 生產庫頻繁手動殺會話 | 應從應用端修正邏輯、加索引、調隔離級別、縮短事務 |
掌握 `V$LOCKED_OBJECT` + `V$SESSION` + `V$PROCESS` 聯查單 SQL 定位阻塞源頭,配合 `KILL SESSION` → `OS KILL` 兩階段終結流程,是 DBA 日常運維的核心技能。長遠治本在於 **應用層統一資源訪問順序、縮短事務邊界、合理索引設計**。