利用logmnr分析历史阻塞会话

利用logmnr分析历史阻塞会话

之前基于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

利用logmnr分析历史阻塞会话_第1张图片

另外也可以用基于事务级别的视图进行查询阻塞的源头,如下:
示例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报告
利用logmnr分析历史阻塞会话_第2张图片

根据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高亮显示相同功能,我们可以很清楚的看出,阻塞会话阻塞的其他会话
利用logmnr分析历史阻塞会话_第3张图片

如上红色的是阻塞者,绿色是被阻塞会话

4、总结

  • 要分析历史阻塞会话,可借助归档日志来分析,但是前提是追加日志要开启
  • 在确定好时间点的情况下,需要知道阻塞会话的session_id,借助logmnr分析上下会话之间的关系
  • 按照scn进行排序后,如果阻塞源头的sql语句在后续scn中出现相同的sql语句,基本可以确定此sql为阻塞的源头

你可能感兴趣的:(logmnr)