ASH(v$active_session_history),相信大家都很熟悉这个视图,作为DBA日常工作中经常使用到的重要性能视图,你对他的了解又有多少呢?今天笔者将从ASH的简单知识点说起,然后说说使用ASH的常见场景(区别于AWR),最后分享几个ASH使用相关的案例。
ASH是oracle 10g开始引入AWR(Automatic Workload Repository)的时候一块引入的,其中AWR的原理见下面这张图:oracle提供了很多v$视图去访问sga内存中的信息,后台进程mmon(维护AWR快照的后台进程)将内存中的信息采集到awr snapshot中,然后oracle又给使用者提供了很多dba_开头的视图去访问awr快照中的信息,所以从图中可以看出这些v$视图和dba_视图其实没有太大的必然联系,这也就意味着ASH和AWR就是两个东西,不能混为一谈,关于这一点后面说到ASH的适用场景的时候就更清楚了。


从上面的图我们知道了dba_hist_active_sess_history视图使用的基表是wrh$_active_session_history,那么v$active_session_history视图使用的基表是什么呢?下面我们就来探究一下:
| select owner,object_name,object_type from dba_objects where object_name='V$ACTIVE_SESSION_HISTORY'; |

是个同义词,接下来我们再看看同义词的视图:
| select owner,SYNONYM_NAME,TABLE_OWNER,TABLE_NAME from dba_synonyms where SYNONYM_NAME='V$ACTIVE_SESSION_HISTORY'; |

| select owner,object_name,object_type from dba_objects where object_name='V_$ACTIVE_SESSION_HISTORY'; |

是个视图,那么我们继续来看看视图的视图:
| select OWNER,VIEW_NAME,TEXT from dba_views where view_name='V_$ACTIVE_SESSION_HISTORY'; |

貌似查了一圈又回到了起点,这条路走不下去了。
再换一条路,有一个视图v$fixed_view_definition,可以查看视图的具体定义:
| select * from v$fixed_view_definition where view_name='V$ACTIVE_SESSION_HISTORY'; |

指向了gv$active_session_history,我们再来看看这个视图的定义:
| select * from v$fixed_view_definition where view_name='GV$ACTIVE_SESSION_HISTORY'; |

很不幸,列太长被截断了,这条路依然没查到。
最后采用下面的方式总算是查到了v$active_session_history所使用的基表:
set autotrace trace select count(*) from v$active_session_history; |

前面已经提到采集ASH信息的进程是oracle 10g新引入的后台进程mmnl,关于这一点我们也来测试验证一下:
先来模拟一个简单的锁:

第一个窗口:
| update t set name='aaaa' where id=1; |
第二个窗口:
update t set name='aaaa' where id=1; ...hang住 |
set line 200 pages 1000 col sample_time for a20 col event for a40 col sql_id for a15 select to_char(sample_time,'yyyymmdd hh24:mi:ss') sample_time, is_awr_sample, session_id sid, blocking_session, sql_exec_id, sql_exec_start, sql_id, event, session_state from v$active_session_history where sample_time>sysdate-(1/24*60) order by 1; |

可以看到,的确是每秒钟采样一次,接下来我们查dba_hist_active_sess_history视图:
select to_char(sample_time,'yyyymmdd hh24:mi:ss') sample_time, session_id sid, blocking_session, sql_exec_id, sql_exec_start, sql_id, event, session_state from dba_hist_active_sess_history where sample_time>sysdate-(1/24*60) order by 1; |

| exec dbms_workload_repository.create_snapshot(); |
再次查询dba_hist_active_sess_history视图:

ps -ef|grep mmnl ---ospid为48508 oradebug setospid 48508 oradebug SUSPEND |

alert日志中会有如下信息:

此时我们再次查询v$active_session_history视图:

可以看到mmnl进程被挂起后,ASH中的信息已经不再刷新了,接下来我们恢复mmnl进程:

alert 日志中会有如下信息:

再次查询v$active_session_history视图:

上面我们已经知道v$active_session_history视图使用的基表是x$ash,那么x$ash又是被存在哪的呢?
select ksppinm,ksppstvl,ksppdesc from sys.x$ksppi x,sys.x$ksppcv y where x.indx=y.indx and upper(ksppinm)='_ASH_SIZE'; select NUM_CHUNKS,TOTAL_SIZE,FIXED_SIZE,FLAGS from x$kewam; select TOTAL_SIZE,FIXED_SIZE,OLDEST_SAMPLE_TIME,LATEST_SAMPLE_TIME from v$ash_info; |


如何清空x$ash?
上面提到"_ash_size"参数修改之后会清空ash buffers中的信息,我们来验证一下:
| alter system set "_ash_size"=10M; |

另外还有一个我个人认为比较鸡肋的隐含参数"_ash_enable"默认为true,修改为false之后表示禁用ash,我们也来看一下吧:
| alter system set "_ash_enable" = false; |

再次启用ash:
| alter system set "_ash_enable" = true; |

我们来回顾一下以上都说了些啥:

最后列出几个和ASH相关的隐含参数:
_ash_disk_filter_ratio
采样到DBA_HIST_ACTIVE_SESS_HISTORY中的频率,默认为10s一次
_ash_disk_write_enable
开启采样到DBA_HIST_ACTIVE_SESS_HISTORY,设置为false则即使创建快照也不会刷新数据到DBA_HIST_ACTIVE_SESS_HISTORY视图中
_ash_eflush_trigger
ASH buffers满了多少以后会写出,默认为66%
_ash_enable
禁用和启用ASH采样
_ash_sample_all
设置为true,则所有会话都会被采样,包括处于空闲等待的会话,默认是false
_ash_sampling_interval
ASH采样间隔时间,默认为1000ms
_ash_size
ASH buffers大小




