之前在一則案例《記錄一則enq: TX - row lock contention的分析過程》使用過這種方法。
因為最近故障處理經常會用到這類查詢進行ASH裸數據的分析,下面以m_ash0902為命名,時間為:2019-09-02 16:00:00 -> 2019-09-02 18:00:00,方便根據實際情況直接進行批量替換。
將客戶的awrdump導入到自己測試環境后,可以直接通過dba_hist_active_sess_history查詢,但推薦還是新建一張表專門存放相關數據,表名以m_ash<日期>命名
create table m_ash0902 tablespace dbs_d_awr as select * from dba_hist_active_sess_history where dbid = &dbid;
注:以下腳本原創作者:Maclean Liu
1.確定異常時刻的top n event
--1.確定異常時刻的top n event
select t.dbid,
t.sample_id,
t.sample_time,
t.instance_number,
t.event,
t.session_state,
t.c session_count
from (select t.*,
rank() over(partition by dbid, instance_number, sample_time order by c desc) r
from (select /*+ parallel 8 */
t.*,
count(*) over(partition by dbid, instance_number, sample_time, event) c,
row_number() over(partition by dbid, instance_number, sample_time, event order by 1) r1
from m_ash0902 t
where sample_time >
to_timestamp('2019-09-02 16:00:00',
'yyyy-mm-dd hh24:mi:ss')
and sample_time <
to_timestamp('2019-09-02 18:00:00',
'yyyy-mm-dd hh24:mi:ss')
) t
where r1 = 1) t
where r < 3
order by dbid, instance_number, sample_time, r;
2.確定最終的top holder
--2.確定最終的top holder
select
level lv,
connect_by_isleaf isleaf,
connect_by_iscycle iscycle,
t.dbid,
t.sample_id,
t.sample_time,
t.instance_number,
t.session_id,
t.sql_id,
t.session_type,
t.event,
t.session_state,
t.blocking_inst_id,
t.blocking_session,
t.blocking_session_status
from m_ash0902 t
where sample_time >
to_timestamp('2019-09-02 16:00:00',
'yyyy-mm-dd hh24:mi:ss')
and sample_time <
to_timestamp('2019-09-02 18:00:00',
'yyyy-mm-dd hh24:mi:ss')
start with blocking_session is not null
connect by nocycle
prior dbid = dbid
and prior sample_time = sample_time
/*and ((prior sample_time) - sample_time between interval '-1'
second and interval '1' second)*/
and prior blocking_inst_id = instance_number
and prior blocking_session = session_id
and prior blocking_session_serial# = session_serial#
order siblings by dbid, sample_time;
3.找出每個采樣點的最終top holder
--3.基於上一步的原理來找出每個采樣點的最終top holder:
select t.lv,
t.iscycle,
t.dbid,
t.sample_id,
t.sample_time,
t.instance_number,
t.session_id,
t.sql_id,
t.session_type,
t.event,
t.seq#,
t.session_state,
t.blocking_inst_id,
t.blocking_session,
t.blocking_session_status,
t.c blocking_session_count
from (select t.*,
row_number() over(partition by dbid, instance_number, sample_time order by c desc) r
from (select t.*,
count(*) over(partition by dbid, instance_number, sample_time, session_id) c,
row_number() over(partition by dbid, instance_number, sample_time, session_id order by 1) r1
from (select /*+ parallel 8 */
level lv,
connect_by_isleaf isleaf,
connect_by_iscycle iscycle,
t.*
from m_ash0902 t
where sample_time >
to_timestamp('2019-09-02 16:00:00',
'yyyy-mm-dd hh24:mi:ss')
and sample_time <
to_timestamp('2019-09-02 18:00:00',
'yyyy-mm-dd hh24:mi:ss')
start with blocking_session is not null
connect by nocycle
prior dbid = dbid
and prior sample_time = sample_time
/*and ((prior sample_time) - sample_time between interval '-1'
second and interval '1' second)*/
and prior blocking_inst_id = instance_number
and prior blocking_session = session_id
and prior
blocking_session_serial# = session_serial#) t
where t.isleaf = 1) t
where r1 = 1) t
where r < 3
order by dbid, sample_time, r;