首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 鎖表查詢與殺進程實戰:V$LOCKED_OBJECT、V$SESSION 關聯定位阻塞源頭

     編輯:Oracle 資料庫基礎

鎖表查詢三層遞進:從「有鎖」到「哪張表」到「誰鎖的」

層級 1:快速確認是否有鎖

-- 統計被鎖物件數
SELECT COUNT(*) FROM V$LOCKED_OBJECT;

-- 列出所有鎖記錄
SELECT * FROM V$LOCKED_OBJECT;

層級 2:定位被鎖表(關聯 DBA_OBJECTS)

SELECT 
    b.OWNER, 
    b.OBJECT_NAME, 
    a.SESSION_ID, 
    a.LOCKED_MODE
FROM V$LOCKED_OBJECT a
JOIN DBA_OBJECTS b ON b.OBJECT_ID = a.OBJECT_ID;

-- LOCKED_MODE 解碼:
-- 0: None, 1: Null (NULL), 2: Row-S (SS), 3: Row-X (SX), 
-- 4: Share (S), 5: S/Row-X (SSX), 6: Exclusive (X)
-- 常見:3=Row-X (DML 鎖), 6=Exclusive (DDL 鎖)

層級 3:定位具體 Session(關聯 V$SESSION)

SELECT 
    b.USERNAME, 
    b.SID, 
    b.SERIAL#, 
    b.LOGON_TIME,
    b.MACHINE,
    b.PROGRAM,
    b.MODULE,
    b.ACTION,
    b.SQL_ID
FROM V$LOCKED_OBJECT a
JOIN V$SESSION b ON b.SID = a.SESSION_ID
ORDER BY b.LOGON_TIME;

進階阻塞鏈分析:誰阻塞了誰?(10g+ V$SESSION.BLOCKING_SESSION)

-- 直接查看被阻塞會話及阻塞者
SELECT 
    s.SID, 
    s.USERNAME, 
    s.EVENT, 
    s.BLOCKING_SESSION,  -- 阻塞者 SID
    s.SECONDS_IN_WAIT, 
    s.WAIT_TIME
FROM V$SESSION s
WHERE s.STATE = 'WAITING'
  AND s.WAIT_CLASS != 'Idle';

殺掉阻塞進程:ALTER SYSTEM KILL SESSION

-- 語法:SID, SERIAL# 從上述查詢獲得
ALTER SYSTEM KILL SESSION '1025,41';

-- 11g+ 立即終止(不等待回滾)
ALTER SYSTEM KILL SESSION '1025,41' IMMEDIATE;

-- PDB 環境(12c+)
ALTER SYSTEM KILL SESSION '1025,41' CONTAINER=CURRENT;

KILL SESSION 原理:標記 Session 為「待終止」,PMON 背景進程清理資源、回滾事務、釋放鎖。**非立即生效**,長事務回滾需時間。IMMEDIATE 讓 PMON 立即強制清理,但可能留下一致性風險(極少見)。

完整排查腳本:一鍵輸出阻塞鏈與殺腳本

SET LINES 200 PAGES 1000
COL owner FOR A20
COL object_name FOR A30
COL username FOR A20
COL machine FOR A30
COL program FOR A40
COL blocker_sid FOR A12

-- 主查詢:被鎖表 + 持有鎖 Session + 等待鏈
SELECT 
    lo.OWNER,
    lo.OBJECT_NAME,
    lo.SESSION_ID AS holder_sid,
    lo.LOCKED_MODE,
    s.USERNAME AS holder_user,
    s.SID,
    s.SERIAL#,
    s.MACHINE,
    s.PROGRAM,
    s.LOGON_TIME,
    sw.EVENT AS holder_wait_event,
    sw.SECONDS_IN_WAIT AS holder_wait_sec,
    bs.SID AS blocker_sid,
    bs.USERNAME AS blocker_user,
    bs.SQL_ID AS blocker_sql_id,
    'ALTER SYSTEM KILL SESSION ''' || s.SID || ',' || s.SERIAL# || ''';' AS kill_cmd
FROM V$LOCKED_OBJECT lo
JOIN DBA_OBJECTS o ON o.OBJECT_ID = lo.OBJECT_ID
JOIN V$SESSION s ON s.SID = lo.SESSION_ID
LEFT JOIN V$SESSION_WAIT sw ON sw.SID = s.SID
LEFT JOIN V$SESSION bs ON bs.SID = s.BLOCKING_SESSION
WHERE o.OWNER != 'SYS'
ORDER BY lo.OWNER, lo.OBJECT_NAME, s.LOGON_TIME;

鎖模式對照表:LOCKED_MODE 數值含義

數值模式名稱縮寫典型操作相容性
0None—無—
1NullNLSELECT(無 FOR UPDATE)全相容
2Row ShareRS / SSSELECT ... FOR UPDATE, LOCK TABLE ... IN ROW SHARE MODE與 RS, RX, S 相容
3Row ExclusiveRX / SXINSERT/UPDATE/DELETE, LOCK TABLE ... IN ROW EXCLUSIVE MODE與 RS, RX 相容
4ShareSCREATE INDEX, LOCK TABLE ... IN SHARE MODE與 RS, S 相容
5Share Row ExclusiveSRX / SSXLOCK TABLE ... IN SHARE ROW EXCLUSIVE MODE僅與 RS 相容
6ExclusiveXDROP/TRUNCATE/ALTER TABLE, LOCK TABLE ... IN EXCLUSIVE MODE全不相容

常見場景與處理建議

場景特徵建議處理
長事務未提交LOCKED_MODE=3/6,SECONDS_IN_WAIT 大聯繫開發確認業務邏輯,決定 KILL 或等待提交
未提交的 DDLLOCKED_MODE=6 (Exclusive)極度危險,**嚴禁生產直接 KILL**,需評估回滾影響
索引重建/統計收集短暫 X 鎖通常秒級自動釋放,無需干預
死鎖ORA-00060,雙方互相等待Oracle 自動檢測犧牲者回滾,檢查 Alert Log 定位 SQL 優化
BITMAP 索引鎖升級大量 DML 導致表級鎖OLTP 環境**禁用 BITMAP 索引**,改用 B-Tree

預防長鎖最佳實踐

  1. 事務極小化:業務邏輯盡量在應用層完成,資料庫層只做「讀-改-寫」最小單元
  2. 避免用戶交互中持有鎖:頁面停留、彈窗確認期間**絕不**持有資料庫事務
  3. 批次作業分批提交:大量 UPDATE/DELETE 每 1000-5000 列 COMMIT 一次
  4. 設定資源限制:PROFILE 限制 IDLE_TIME、CONNECT_TIME,配合 DRM MAX_IDLE_TIME
  5. 監控告警:Enterprise Manager / 自製腳本監控 SECONDS_IN_WAIT > 300 且 BLOCKING_SESSION IS NOT NULL 發送告警

總結

鎖表排查核心路徑:**V$LOCKED_OBJECT → DBA_OBJECTS(哪張表)→ V$SESSION(誰鎖的)→ V$SESSION.BLOCKING_SESSION(誰被誰阻)**。掌握 LOCKED_MODE 含義與 ALTER SYSTEM KILL SESSION 'sid,serial#' [IMMEDIATE] 語法,建立「一鍵輸出阻塞鏈+殺腳本」標準腳本,是 DBA 應對生產阻塞事件的必備基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved