之前基于ash会话级视图可以查当前阻塞以及被阻塞的会话信息,如下:
示例1:
select sample_time,sql_text,session_id,session_serial#,session_type,b.sql_id,
event,blocking_session,blocking_session_serial#,
blocking_inst_id from gv$active_session_history a,gv$sqlarea b where
session_id=5 and session_serial#=171 and a.SQL_ID=b.SQL_ID order by sample_id asc
另外也可以用基于事务级别的视图进行查询阻塞的源头,如下:
示例2
with ltr as (
select to_char(sysdate,'YYYYMMDDHH24MISS') TM,
s.inst_id,
s.sid,
s.serial#,
s.status,
s.sql_id,
s.sql_child_number,
s.prev_sql_id,
xid,
t.start_scn,
to_char(t.start_date,'YYYY-MM-DD HH24:MI:SS') start_time,
e.TYPE,e.block,
e.ctime/3600 runtime_Hour,
decode(e.CTIME, 0, (sysdate - t.start_date) * 3600*24, e.ctime) el_second
-- q.sql_text
from gv$transaction t, gv$session s,gv$transaction_enqueue e
where t.start_date <= sysdate - interval '1' second /*查询开始多少秒的事务*/
and t.addr = s.taddr
--and s.sql_child_number = q.CHILD_NUMBER(+)
--and s.sql_id = q.sql_id(+) and s.prev_sql_id = q.sql_id(+)
and t.addr = e.addr(+) )
select ltr.* , (select q1.sql_text from gv$sql q1 where ltr.prev_sql_id = q1.sql_id(+)
and rownum = 1) prev_sql_text ,
(select q1.sql_text from gv$sql q1 where ltr.sql_id = q1.sql_id(+)
and ltr.sql_child_number = q1.CHILD_NUMBER(+)) sql_text
from ltr ltr;
示例1是基于事务,主要查询的是还在进行中,未完成的事务,此脚本虽然可以查出阻塞的源头,但是无法取得阻塞的sql。
示例3
SELECT A.INST_ID,A.SID,A.SERIAL#,A.USERNAME,A.EVENT,A.WAIT_CLASS,A.SECONDS_IN_WAIT,A.PREV_EXEC_START,b.LOCKED_MODE,C.OWNER,C.OBJECT_NAME,C.OBJECT_TYPE
FROM gV$SESSION A
INNER JOIN gV$LOCKED_OBJECT B
ON A.SID=b.SESSION_ID
INNER JOIN DBA_OBJECTS C
ON B.OBJECT_ID=c.OBJECT_ID
WHERE A.WAIT_CLASS='Idle'
AND A.SECONDS_IN_WAIT>1
以上示例1-3,只能查当前阻塞与被阻塞的信息,一旦ash在内存中被”flush“掉,就无法获取历史阻塞信息。
虽然Oracle没有直接提供查找阻塞源头sql的方法,然而根据项目中多次实践、探究,我梳理了间接查找历史阻塞会话的方法
1、先确定好环境中阻塞发生的时间点,拉取ash报告
根据blocking session的% Activity与top sessions中一样,可以判断出,会话4189阻塞了上面会话6245
2、在开启追加日志的前提下,捞取阻塞会话信息
阻塞会话与被阻塞会话在logmnr中的记录
select scn,
timestamp,
start_scn,
commit_scn,
xid,
operation,
seg_name,
sql_redo,
machine_name,
session_info,
thread#,
session#,
serial#
from archdump
where (
(session# = 4189 and serial# = 2382) or --blocking
(session# = 2925 and serial# = 4336) or --blocking
(session# = 3321 and serial# = 45918) or --blocking
(session# = 6245 and serial# = 39240) or --blocked
(session# = 2688 and serial# = 57682) --blocked
(session# = 2846 and serial# = 4244) or --blocked
(session# = 3320 and serial# = 42418)
) --blocked
and scn >= 791019425
and scn <= 791125745
and seg_name = 'FRAME_ONLINEUSER'
order by scn asc
3、在借助PL/SQL高亮显示相同功能,我们可以很清楚的看出,阻塞会话阻塞的其他会话
如上红色的是阻塞者,绿色是被阻塞会话
4、总结