暂无图片
暂无图片
10
暂无图片
暂无图片
暂无图片

ASH体系结构及相关知识点

取名浪费我半小时 2020-11-10
7201


       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的适用场景的时候就更清楚了。



      v$active_session_history每秒采集一次数据库活动会话,所谓的活动会话,就是采集的时间点如果某个会话处于ON CPU或者正在等待一个非空闲等待事件,那么这个会话就被认为是活动会话。其中采集ASH信息的进程也是oracle 10g新引入的后台进程mmnl

     dba_hist_active_sess_history是v$active_session_history的持久化视图,他通过mmon进程将v$active_session_history中的信息每十秒采集一次到awr snapshot中,但是这里有一点需要注意,并不是说每过10秒我就能在dba_hist_active_sess_history中查到过去刚发生的活动会话信息,这里还有很多其他的触发条件,比如如果我们的系统很空闲,ash buffer只用了一点点(ash buffer使用达到66%会自动触发mmon进行快照),那么我们可能就会遇到在v$active_session_history能查到某个会话(超过十秒),但是在dba_hist_active_sess_history中却查不到,即使等待超过10秒后再查依然查不到,这属于正常现象,这时候我们可以手动创建一个快照,之后便能在dba_hist_active_sess_history中查到相应的会话信息了。

       关于v$active_session_history和dba_hist_active_sess_history这两个视图的关系看下图可能更直观:图中mmon进程将v$active_session_history中的信息采集到基表WRH$_ACTIVE_SESSION_HOSTORY中,然后dba_hist_active_sess_history视图从WRH$_ACTIVE_SESSION_HOSTORY基表中获取数据,最终将相关信息展示到AWR report中,这里AWR是直接从基表中获取数据还是从dba_视图或者v$视图中获取数据这里就不在探究了,创建快照的时候收个10046事件应该就能很清楚的看到了。



  •       从上面的图我们知道了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;



     可以看到最晚的采样时间只到21:47分,这也就验证了前面我们所说的v$active_session_history视图中能查到会话信息,而dba_hist_active_sess_history中却查不到的情况,此时我们手动创建一个快照:


exec dbms_workload_repository.create_snapshot();


再次查询dba_hist_active_sess_history视图:



    可以看到v$active_session_history中的信息在创建快照后被刷到了dba_hist_active_sess_history视图中。

       现在我们将mmnl进程挂起,如果mmnl负责采集ASH信息,那么可以预想到当进程挂起后,ASH中将不再能查到实时的活动会话信息。


ps -ef|grep mmnl     ---ospid为48508


oradebug setospid 48508


oradebug SUSPEND



alert日志中会有如下信息:



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



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



alert 日志中会有如下信息:



再次查询v$active_session_history视图:



       可以看到ASH中因为mmnl进程中途被挂起了一段时间而出现了断档,断档的时间点和alert日志中打出的信息是能对应上的,并且在mmnl进程恢复之后,会话信息得以重新采集。至此也就验证了mmnl进程就是负责采集ASH信息的后台进程。

       这里插一句,oradebug命令真的很强大,除了平时我们各种dump操作时经常用到,还有就是上面的案例中用到的进程挂起以及恢复功能,对于我们模拟一些实际的生产问题很有用。例如我们可以模拟某一个进程宕了或者hang了之后会发生什么?还可以探究某些后台进程之间的关系,以及某些后台进程的原理理解等等,比如我们模拟将ARCn进程挂起,多次切换日志,直到切换动作hang住,我们就明白了ARCn进程的用途,以及如果ARCn进程hang了会产生什么样的结果。


  • 上面我们已经知道v$active_session_history视图使用的基表是x$ash,那么x$ash又是被存在哪的呢?

     x$ash数据存放在Shared Pool的ASH Buffer中,大小由隐含参数"_ash_size"决定。


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$kewam是v$ash_info视图的基表。ash buffers的大小默认是由cpu的个数以及shared pool size的大小决定的(具体算法见下图),当然也是可以通过隐含参数"_ash_size"来在线动态修改。但是这里需要格外注意,修改"_ash_size"参数后ash buffers中的数据会被清空,所以在修改此参数之前务必要将ash中的数据导出备份。




  • 如何清空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中的信息又回来了,有点侮辱智商的赶脚。




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




      上面的图片很好的说明了ASH的体系结构,其中x$ksuse是gv$session视图所使用的基表,同样可以通过前面的方法查到(set autotrace trace)。首先mmnl进程从gv$session动态性能视图中采集信息,默认每秒采集一次,然后将采集的信息写入到ash buffers中,此时活动会话信息已经进入到x$ash基表中,然后gv$active_session_history视图从x$ash基表中读取数据,mmon进程负责对gv$active_session_history视图中的信息进行持久化,持久化到wrh$_active_session_history基表中,而dba_hist_active_sess_history视图中的数据又是来源于wrh$_active_session_history基表。可以看到ash相关的部分除了需要mmon进程进行持久化到awr,实际上正如前边所说的,ash 和 awr是两个不同的东西,不能混为一谈。



  • 最后列出几个和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大小




      本来计划着继续说ASH常见的应用场景,以及相关案例的,篇幅原因,下次再补吧。
      最后非常感谢卞其龙提供的相关素材,以及下期将要分享的ASH相关的案例,所以这期严格意义上来讲只是我的总结与整理。我一直都认为,会用一个知识往往不难,但要向别人解释清楚这个事就并不简单了,这背后需要你去了解并掌握更多的相关知识所涉及到的原理。所以我也正是想利用这种方式,来加深自己对知识的理解与掌握。







最后修改时间:2020-11-23 09:57:50
文章转载自取名浪费我半小时,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论