由latch引起的cpu消耗高

本实验是测试由于latch引起过高的cpu资源。我们使用以下实验来模拟。

首先我们查找一下有关于latch的隐含参数
查询当前实例一共有多少个lathc.实用下面的SQL来查询。
column name format a42
column value format a24

select
  x.ksppinm  name,
  y.ksppstvl  value,
  y.ksppstdf  isdefault,
  decode(bitand(y.ksppstvf,7),1,'MODIFIED',4,'SYSTEM_MOD','FALSE')  ismod,
  decode(bitand(y.ksppstvf,2),2,'TRUE','FALSE')  isadj
from
  sys.x$ksppi x,
  sys.x$ksppcv y
where
  x.inst_id = userenv('Instance') and
  y.inst_id = userenv('Instance') and
  x.indx = y.indx and x.ksppinm like '%latch%'
order by
  translate(x.ksppinm, ' _', ' ');

NAME                                VALUE                                              ISDEFAULT ISMOD      ISADJ
----------------------------------- -------------------------------------------------- --------- ---------- -----
_db_block_hash_latches              4096                                               TRUE      FALSE      FALSE
_db_block_lru_latches               96                                                 TRUE      FALSE      FALSE
_db_blocks_per_hash_latch                                                              TRUE      FALSE      FALSE
_disable_latch_free_SCN_writes_via_ FALSE                                              TRUE      FALSE      FALSE
32cas                                                                                                      
_disable_latch_free_SCN_writes_via_ FALSE                                              TRUE      FALSE      FALSE
64cas                                                                                                      
_enable_reliable_latch_waits        TRUE                                               TRUE      FALSE      FALSE
_enqueue_hash_chain_latches         24                                                 TRUE      FALSE      FALSE
_flashback_copy_latches             10                                                 TRUE      FALSE      FALSE
_gc_latches                         8                                                  TRUE      FALSE      FALSE
_gcs_latches                        0                                                  TRUE      FALSE      FALSE
_kgl_latch_count                    0                                                  TRUE      FALSE      FALSE
_kgx_latches                        512                                                TRUE      FALSE      FALSE
_ktc_latches                        0                                                  TRUE      FALSE      FALSE
_ktu_latches                        0                                                  TRUE      FALSE      FALSE
_latch_class_0                                                                         TRUE      FALSE      FALSE
_latch_class_1                                                                         TRUE      FALSE      FALSE
_latch_class_2                                                                         TRUE      FALSE      FALSE
_latch_class_3                                                                         TRUE      FALSE      FALSE
_latch_class_4                                                                         TRUE      FALSE      FALSE
_latch_class_5                                                                         TRUE      FALSE      FALSE
_latch_class_6                                                                         TRUE      FALSE      FALSE
_latch_class_7                                                                         TRUE      FALSE      FALSE
_latch_classes                                                                         TRUE      FALSE      FALSE
_latch_miss_stat_sid                0                                                  TRUE      FALSE      FALSE
_latch_recovery_alignment           998                                                TRUE      FALSE      FALSE
_lm_drm_xlatch                      0                                                  TRUE      FALSE      FALSE
_lm_num_pcmhv_latches               0                                                  TRUE      FALSE      FALSE
_lm_num_pt_latches                  128                                                TRUE      FALSE      FALSE
_max_sleep_holding_latch            4                                                  TRUE      FALSE      FALSE
_num_longop_child_latches           24                                                 TRUE      FALSE      FALSE
_session_idle_bit_latches           0                                                  TRUE      FALSE      FALSE
_ultrafast_latch_statistics         TRUE                                               TRUE      FALSE      FALSE
32 rows selected
再来查询一下当前实例数据库中有多少个数据块。    
select count(*) from v$bh;
  COUNT(*)
----------
    140922
根据上面的两个查询语句,我们发现140922个数据块被4096个latch管理。

 

--查看每个latch管理的块数
select HLADDR ,count(*) from x$bh group by rollup(HLADDR );

由于数据太多,我只截一部分图,我们发现每个latch大约管理30多个数据块。
HLADDR             COUNT(*)
---------------- ----------
0000000138356438         32
0000000138356700         39
00000001383569C8         32
0000000138356C90         31
0000000138356F58         34
0000000138357220         37
00000001383574E8         35
00000001383577B0         39
0000000138357A78         27
0000000138357D40         38
0000000138358008         33
00000001383582D0         36
0000000138358598         36
0000000138358860         40
0000000138358B28         28
0000000138358DF0         33
00000001383590B8         36
0000000138359380         32
0000000138359648         30
0000000138359910         31
0000000138359BD8         29
0000000138359EA0         32
000000013835A168         37

--查询锁的丢失情况
select CHILD# ,ADDR , GETS , MISSES , SLEEPS
from v$latch_children
where name = 'cache buffers chains'
and misses>100000
order by 4, 1, 2, 3;

    CHILD# ADDR                   GETS     MISSES     SLEEPS
---------- ---------------- ---------- ---------- ----------
      1571 00000001384672C8 1425958067     105284          1
      3042 0000000138566E00 2389392407     192232         14
根据上面的基数,我们来开始我们的实验。
首先我们建立一个测试表t1,向表中插入一些数据。
使用一个匿名块同事查询表t1。同时开10个回话。

--开10个会话,其中表t1有几万行的数据,同时运行,立刻查询上面的语句
declare
v1 emp.sal%type;
begin
for n in 1..100 loop
for k in 1..100 loop
select count(*) into v1 from t1;
end loop;
dbms_lock.sleep(1);
end loop;
end;
/


SQL> select name,gets,misses from v$latch where name='cache buffers chains';

NAME                                             GETS     MISSES
------------------------------------------ ---------- ----------
cache buffers chains                         68121210    6701801

我们不断的运行,misses迅猛的增加。
那么这里给大家解释下,什么是GETS,什么是MISSES,GETS就是记录你向oracle请求查询的次数,
而misses那,是你向oracle请求,但是由于oracle比较繁忙,不能答复您的请求,也就是不能答复您的次数。
打个比方,我们在办公室经常会使用到会议室,但是公司只有一个会议室,大家都想使用这个会议室,而这时会议室正在被占用,你想使用,但是
您还不知道什么时候能使用完,您就过一会儿,去看一看有没有人在占用,一看还在占用,你就回去等。反复去查看使用
情况,您去查看的次数也就是GETS的数量,MISSES就是您发现还在占用的次数。
在数据库中,MISSES的次数越多,说明某一个数据对象越繁忙。那么数据库的速度就越慢。

因此我们要定位热点的对象,我们可以通过下面的语句来定位数据库中MISSES次数比较多的对象。
--找到哪些misses的比较多。如果100000选出来的太多,根据不同的情况,你可以加大MISSES的次数。
 select CHILD# ,ADDR , GETS , MISSES , SLEEPS
 from v$latch_children
 where name = 'cache buffers chains'
 and misses>100000
 order by 4, 1, 2, 3;

CHILD# ADDR           GETS     MISSES     SLEEPS
------ -------- ---------- ---------- ----------
   924 699B50C0    1271177     127078         21
   590 699A5640    1205164     127715         22
   291 69997600    1205428     127716         32
   981 699B7B80    2405417     185470         65

--根据addr的列,找到文件号和块号,在找到对象
select a.owner,a.segment_name,count(*) from
dba_extents a,
(select dbarfil,dbablk from x$bh where hladdr in('699B50C0' ,'699A5640' ,'69997600' ,'699B7B80' )) b
where a.RELATIVE_FNO = b.dbarfil
and a.BLOCK_ID <= b.dbablk and a.block_id + a.blocks > b.dbablk
group by a.owner,a.segment_name;

OWNER                          SEGMENT_NAME           COUNT(*)
------------------------------ -------------------- ----------
SYS                            C_TOID_VERSION#               4
SYS                            I_OBJ#                        1
SYS                            IDL_SB4$                      1
SCOTT                          T1                            9
SYS                            C_OBJ#                        1

其中scott.t1表是我们自己的业务表。有9个块,因为我们只取了前几位的地址。
可以判断scott.t1为热点。
虽然t1表在内存中,我们可以命中,但要读取,还要通过latch,如果应用太集中,
都访问一个表,必然造成这个结果。
现在不是内存小了,而是访问模式太集中了,现象为cpu的负载过高。latch丢失严重。

解决的办法为分散应用,增加或者减少索引!
SQL> create bitmap index  scott.i1 on scott.t1(deptno);

索引已创建。

SQL> select name,gets,misses from v$latch where name='cache buffers chains';

NAME                                             GETS     MISSES
------------------------------------------ ---------- ----------
cache buffers chains                        131912045   12869688

--现在我们再次在10个会话中运行刚才的测试程序。等结束后再次查询。
NAME                                             GETS     MISSES
------------------------------------------ ---------- ----------
cache buffers chains                        132112739   12869695
发现只有极少的增加,可以忽略不计。原来增加了600万的misses.
总结:
从这个小实验,我们懂得了什么是热点块。
通过改变sql的运行来改变热点。
数据库优化无止境!要多揣摩,多动手,多思考!

 



pxboracle@live.com
2014.08.11 13:28
share you knowledge with the world.  

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12798004/viewspace-1249146/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12798004/viewspace-1249146/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值