鎖機制是Oracle用來滿足隔離性,一緻性的重要機制。但是不合理的業務邏輯可能導緻死鎖的産生,生産環境如果發生大量死鎖,可能對業務造成很大的影響,是以必須及時處理。
發現死鎖
通過 dba_blockers 視圖,可以查到死鎖的程序。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL3YjMyQTMxUTM3ETMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
我這裡由于是 19c ,是以多了一列 CON_ID ,表示哪個 pdb。
定位 session
-- 通過以下 SQL 定位死鎖發生的 session 及 對象
select lo.session_id,
s.serial#,
s.username,
o.name,
s.lockwait,
s.status,
s.machine,
s.program
from v$session s, v$locked_object lo, obj$ o
where s.sid = lo.session_id
and lo.object_id = o.obj#;
字段名 | 含義 |
---|---|
SESSION_ID | Session ID 。與 SERIAL# 共同确定會話 |
SERIAL# | Session serial number(會話編号)。與 SESSION_ID 共同确定會話 |
USERNAME | Oracle username 。被鎖語句的執行者 |
NAME | 被鎖對象的名字 |
LOCKWAIT | Address of the lock the session is waiting for; NULL if none |
STATUS | Status of the session |
MACHINE | Operating system machine name (主機名) |
PROGRAM | Operating system program name (連接配接用得用戶端類型) |
Status of the session:
- ACTIVE - Session currently executing SQL
- INACTIVE
- KILLED - Session marked to be killed
- CACHED - Session temporarily cached for use by Oracle*XA
- SNIPED - Session inactive, waiting on the client
-- 通過以下 SQL 可以定位到被阻塞的 SQL 文本
select sql_text
from v$sql
where hash_value in
(select sql_hash_value
from v$session
where sid in (select session_id from v$locked_object));
解決問題
解決死鎖的方式一般就是殺掉一個 session。
通過上面的查詢定位到了一對 session ,其中 session_id 1457 的 session 阻塞了 session_id 1698 的 session。
那麼最好的處理辦法事殺掉 session_id 1457 的 session (也就是造成阻塞的 session),這樣 被阻塞的 session 上的 SQL 還可以繼續執行。也可以殺掉被阻塞的 session ,這樣被阻塞 session 上的 SQL 就會失敗(不推薦)。
-- 殺掉 session 的 SQL
alter system kill session 'session_id,serial#';
-- 該例子中使用的語句如下:
alter system kill session '1457,63336';
總結
如果生産系統經常出現死鎖,肯定是程式有邏輯上的問題。這個時候就需要通過定位 SQL 找到死鎖的原因,才能從根本上解決問題。