記一次Oracle死鎖/阻塞排查
阿新 • • 發佈:2021-12-21
記一次Oracle死鎖/阻塞排查
Im_Coder 2019.01.15 17:59:53字數 269閱讀 2,8611. 檢查資料庫確定 是否 真實存在死鎖,若有 哪臺機器哪個程式。
select username, lockwait, status, machine, program
from v$session
where sid in (select session_id from v$locked_object);
--Username:死鎖語句所用的資料庫使用者;
--Lockwait :死鎖的狀態,如果有內容表示被死鎖。
--Status :狀態,active表示被死鎖
--Machine :死鎖語句所在的機器。
--Program :產生死鎖的語句主要來自哪個應用程式。
2. 確定死鎖後,還可以檢查是哪個語句產生死鎖等待。
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));
3. 查詢未提交事務的SQL,大概率是其引起。
select s.sid,
s.username,
s.osuser,
s.program,
to_char(s.LOGON_TIME, 'yyyymmdd hh24:mi:ss') as LOGON_TIME,
to_char(t.START_DATE, 'yyyymmdd hh24:mi:ss') as START_DATE,
s.status,
(select q.SQL_TEXT from v$sql q where q.LAST_ACTIVE_TIME = t.START_DATE
and rownum <= 1) as SQL_TEXT
from v$session s,
v$transaction t
where s.sADDR = t.SES_ADDR;
4. 若找不到對應的User,則可以通過kill掉死鎖的session程序
SELECT l.SESSION_ID, l.OS_USER_NAME, s.USERNAME, l.OBJECT_ID, l.ORACLE_USERNAME
FROM v$locked_object l,
v$session s
WHERE l.SESSION_ID = s.SID;
5. 根據SessionID查詢鎖表語句
select sql_text
from v$sql
where hash_value in
(select sql_hash_value from v$session where sid in (208));
6. 檢視死鎖
select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.object_name, lo.locked_mode, SESS.machine
from v$locked_object lo,
dba_objects ao,
v$session sess
where ao.object_id = lo.object_id
and lo.session_id = sess.sid;
對v$locked_object被鎖物件進行查詢:
SELECT l.session_id sid,
s.serial#,
l.locked_mode,
l.oracle_username,
l.os_user_name,
s.machine,
s.terminal,
o.object_name,
s.logon_time
FROM v$locked_object l, all_objects o, v$session s
WHERE l.object_id = o.object_id AND l.session_id = s.sid
ORDER BY sid, s.serial#;
鎖表sql
分析上圖結果:
第1個Session的id為139對LN_DUE進行了鎖表操作,第2個session的id為141對LN_DUE進行了鎖表操作,於是死鎖產生了。原因為程式碼中使用了兩個Connection,前一個Connection執行完update語句未提交,導致行級鎖未釋放,第2個Connection又去對同一個表進行update,於是只能等待前一個connection釋放行級鎖。
解決:
alter system kill session '139,6151';
139是查詢結果中的SID欄位,6151是查詢結果中的SERIAL