Oracle Latch internals随笔三

日期: 2008-06-09 来源:TechTarget中国

  要分析一个latcha free事件,其中一个办法就是检查statspack report。首先我们应该看wait events waited fro by the foreground processes。例如:

  Wait Events for DB: GDDB1 Instance: gddb1 Snaps: 127 -128
  -> s – second
  -> cs – centisecond – 100th of a second
  -> ms – millisecond – 1000th of a second
  -> us – microsecond – 1000000th of a second
  -> ordered by wait time desc, waits desc (idle events last)

  Avg
  Total Wait wait Waits
  Event Waits Timeouts Time (s) (ms) /txn
—————————- ———— ———- ———- —— ——–

  latch free 97 14 73 749 0.0
  log file sync 7,458 16 29 4 0.6
  db file parallel write 863 0 22 26 0.1
  log file parallel write 7,456 7,433 9 1 0.6
  control file parallel write 1,484 0 6 4 0.1
  db file sequential read 865 0 4 5 0.1
  ARCH wait on SENDREQ 100 0 3 29 0.0
  async disk IO 106 0 0 2 0.0
  SQL*Net more data to client 19,083 0 0 0 1.5
  direct path write 56 0 0 3 0.0
  log file sequential read 66 0 0 2 0.0
  direct path write (lob) 1,888 0 0 0 0.2
  control file sequential read 4,365 0 0 0 0.3
  direct path read (lob) 5,637 0 0 0 0.5
  buffer busy waits 18 0 0 1 0.0
  db file scattered read 3 0 0 2 0.0
  enqueue 1 0 0 6 0.0
  log file single write 4 0 0 0 0.0
  direct path read 56 0 0 0 0.0
  LGWR wait for redo copy 1 0 0 0 0.0
  SQL*Net message from client 322,043 0 43,011 134 25.8
  PX Idle Wait 4,320 4,320 8,603 1991 0.3
  SQL*Net message to client 322,044 0 0 0 25.8
  SQL*Net more data from clien 4,371 0 0 0 0.3

  然后观察Latch Activity部分。这里主要描述那些特定的事件为瓶颈。Pct Misseses对于willing-to-wait和no-wait latches应该接近为0.0。
  Latch Activity for DB: GDDB1 Instance: gddb1 Snaps: 127 -128
  ->”Get Requests”, “Pct Get Miss” and “Avg Slps/Miss” are statistics for
  willing-to-wait latch get requests
  ->”NoWait Requests”, “Pct NoWait Miss” are for no-wait latch get requests
  ->”Pct Misses” for both should be very close to 0.0
  Pct Avg Wait Pct
  Get Get Slps Time NoWait NoWait
  Latch Requests Miss /Miss (s) Requests Miss
———————— ————– —— —— —— ———— ——

  session timer 736 0.0 0 0
  shared pool 774,157 0.0 0.0 0 0
  sim partition latch 0 0 31 0.0
  simulator hash latch 42,279 0.0 0 0
  simulator lru latch 178 0.0 0 309 0.0
  sort extent pool 43 0.0 0 0
  transaction allocation 642 0.0 0 0
  transaction branch alloc 35 0.0 0 0
  undo global data 28,014 0.0 0.0 0 0
  user lock 186 0.0 0 0

  接下来看看Latch sleep breakdown statspack section report部分。主要报告那些latch被服务器进程spinning和sleeping。这个部分是用Misses来排序的,但我们主要关注sleeps的统计信息。
Latch Sleep breakdown for DB: GDDB1 Instance: gddb1 Snaps: 127 -128
  -> ordered by misses desc

  Get Spin &
  Latch Name Requests Misses Sleeps Sleeps 1->4
————————– ————– ———– ———– ————

  library cache 1,042,559 506 64 443/62/1/0/0
  shared pool 774,157 384 16 368/16/0/0/0
  cache buffers chains 1,731,469 44 14 0/0/0/0/0
  redo allocation 137,179 21 3 18/3/0/0/0

  下面用这个例子说明如果跟踪到当cache buffers chains sleeps显著时,出现的所谓“热点块”(hot blocks)。
  1、创建两个临时表,用来装载sleeps统计信息。
  SQL> create table sleep_buf_chains_a as
  2 select addr,child#,sleeps
  3 from v$latch_children
  4 where name=’cache buffers chains’;

  Table created.
  等待20秒后,在创建一个临时表。
  SQL> create table sleep_buf_chains_b as
  2 select addr,child#,sleeps
  3 from v$latch_children
  4 where name=’cache buffers chains’;
  2、join两个表,两个表最近的sleeps的差异,然后在排序。最后两行数据应该是所谓的热点数据块。
  SQL> select a.addr,a.child#,
  2 (b.sleeps-a.sleeps) sleeps
  3 from sleep_buf_chains_a a,sleep_buf_chains_b b
  4 where a.addr=b.addr
  5 and sleeps >0
  6 order by sleeps;
  例如得到如下数据:
  Addr chile sleeps
  901135FC 1871 178
  900BF5FC 335 179
  9010AD7C 1715 208
  901064DC 1632 215
  9010615C 1628 294

  3、使用x$bh试图得到实际的热点块。
  select hladdr,tch,ts#,file#,dbablk, class,
  Decode(state, 2,’shared current’,
  3, ’cr version’,
  1, ’exclusive current’,0)
  From x$bh
  where hladdr in(’9010AD7C’,’901064DC’,’010615C’) and tch >100
  Order by tch,hladdr,dbablk;

  HLADDR TCH TS# FILE# DBABLK CLASS ECODE(STATE,2,’S
——– ———- ———- ———- ———- ———- —————–
  9010AD7C 129 11 17 6800 1 shared current
  9010AD7C 137 1 2 9 17 0
  9010AD7C 193 7 7 20721 1 shared current
  9010AD7C 350 7 7 10481 1 shared current
  9010AD7C 403 14 25 61469 9 0
  9010AD7C 459 10 14 6960 1 shared current
  901064DC 973 14 22 18538 1 exclusive current
  9010AD7C 2543 14 22 18621 1 exclusive current

  8 rows selected.
  4、依据上步中查到的file_id和block id,查询dba_extents得到实际的相应的对象。查询dba_segment可以得到freelist的数量,增加这个数值,可以减少相应的数据块竞争。
  SQL> col SEGMENT_NAME format a25
  SQL> select segment_name,segment_type,owner,tablespace_name
  from dba_extents
  where file_id=22
  and 18621 between block_id and (block_id +(blocks-1));

  SEGMENT_NAME SEGMENT_TYPE OWNER TABLESPACE_NAME
————————- —————— ——————————
  SYS_IL0000006840C00003$$ LOBINDEX MAILCONTENT MAILCONTENT

  SQL> select segment_name,segment_type,owner,tablespace_name
  from dba_extents
  where file_id=7
  and 20721 between block_id and (block_id +(blocks-1));

  SEGMENT_NAME SEGMENT_TYPE OWNER TABLESPACE_NAME
————————- —————— ——————————
  PK_EMAILID_MAILID INDEX MTAMANAGER MTAINDEX

  使用v$session_event和V$system_event试图可以得到一个累计统计信息,而v$session_wait可以道道实时的等待信息,其中P1为Latch地址(latch address),P2为Latch号(latch number)。还有一些有用的试图v$latch_misses、v$latch、v$latch_parent、v$latch_children、v$latchholden和v$latch_misses。如:
  SQL> select distinct l.name “latch” from v$session_wait s, v$latch l
  where s.p2=l.latch#
  and s.event=’latch free’
  and s.wait_time=0;

  一些需要特别注意的latches,比如cache buffers chains、row cache objects、redo copy、library cache、shared pool、cache buffers LRU chain和redo allocation。
  当latch在系统范围内的等待时间比较显著时,你可以通过v$latch中的sleeps列来发现争用显著的latch。
  SQL>select name, gets, misses, immediate_gets, immediate_misses, sleeps
  from v$latch
  order by sleeps desc;

  shared pool 2516471776 2851975 0 0 127747
  cache buffers chains 12028546317 222992 77269891 78814 31983
  library cache 2739913072 1780652 89077598 325519 19093

  对于不同的latch,其产生的原因以及可采取的对策都有所不同。详细的说明所有的latch可以写成一本书了。这里我们只选择最常见的五个latch加以说明:shared pool, library cache, cache buffers chains, cache buffers lru chain和row cache objects。
  Shared pool 和 library cache latch的争用,有可能是由于硬分析造成。Oracle的共享池由不同的结构组成。主要包括:数据字典缓存,sql区和库缓存。通过v$sgastat你可以查看其他一些结构。Shared pool latch主要用来保护共享池的内存结构,当分配或者释放共享池内存时需要先获得该latch。例如,为一个新的sql语句或pl/sql过程、函数、包,触发器等分配空间(硬解析)时,或者为换出、清除某些内存块,以便为新的对象腾出足够的空间时,都需要获取shared pool latch。
  在oracle9i之前,共享池内存结构由一个独立shared pool latch保护,从9i开始,则有最多7个子latch可以用于共享池的保护。这也是为什么oracle9i可以将共享池分成多个子共享池的原因(服务器至少需要4颗cpu,并且shared_pool_size大于250m才能使用多个子共享池的特性)。子共享池的个数可以通过隐含参数_kghdsidx_count手动调节,该参数同时会指定合适的shared pool子latch的个数。如果你手动增加子共享池的个数,你应该同时增加shared_pool_size的值,因为每个子共享池都有自己的结构,lru列表和shared pool latch。否则,实例启动时可能会遇到以下错误:
  Ora-04031: unable to allocate 32 bytes of shared memory (“shared pool”,”unknown object”,”sga heap(5,0)”,”fixed allocation callback”).
  下面的统计信息是从一个4颗cpu,shared_pool_size为256m的oracle9i数据库中读取的。由_kghdsidx_count参数可知共享池被分成2个子池,通过x$kghlu(kernel generic heap lru)可以知道lru列表也有2个。v$latch_children视图显示了7个子latch中的2个已经被使用。
  SQL>select a.ksppinm, b.ksppstvl
  from x$ksppi a, x$ksppsv b
  where a.indx = b.indx
  and a.ksppinm = ’_kghdsidx_count’;

  通过以下语句可以查处LRU列表。
  SQL> select addr, kghluidx, kghlufsh, kghluops, kghlurcr, kghlutrn, kghlumxa from x$kghlu;

  ADDR KGHLUIDX KGHLUFSH KGHLUOPS KGHLURCR KGHLUTRN KGHLUMXA
——– ———- ———- ———- ———- ———- ———-
  B79E8450 2 40452680 565459699 26231 69949 2147483647
  B79E745C 1 48896624 531238837 20427 60700 2147483647

  Shared pool和library cache latch争用通常是由于硬分析引起。硬分析需要分配新的游标,或者将已经换出的游标重新执行。硬分析过多说明sql语句没有充分绑定变量。硬分析是代价十分昂贵的操作,在分析期间需要一直持有ibrary cache latch。通过下列查询可以发现系统中是否存在大量硬分析。软分析数则可以用总分析数减去硬分析数获得。
  SQL>select a.*, sysdate-b.startup_time days_old
  from v$sysstat a, v$instance b
  where a.name like ’parse%’;
  STATISTIC# NAME CLASS VALUE DAYS_OLD
———- ————————- ———- ———- ———-
  230 parse time cpu 64 4146221 177.90375
  231 parse time elapsed 64 4595596 177.90375
  232 parse count (total) 64 152359500 177.90375
  233 parse count (hard) 64 29918794 177.90375
  234 parse count (failures) 64 369 177.90375

  备注:分析失败可能是由于“ora-00942: table or view does not exist”错误或者共享内存不足。
  
  查看当前会话是否有大量硬分析的语句。
  SQL> select a.sid, c.username, b.name, a.value,
  round((sysdate – c.logon_time)*24) hours_connected
  from v$sesstat a, v$statname b, v$session c
  where c.sid = a.sid
  and a.statistic# = b.statistic#
  and a.value > 0
  and b.name = ’parse count (hard)’
  order by a.value;

  SID USERNAME NAME VALUE HOURS_CONNECTED
———- ————— ————————- ———- —————
  45 GZYW parse count (hard) 12 4
  30 GZYW parse count (hard) 16 4
  82 MTAMANAGER parse count (hard) 36 4
  16 parse count (hard) 112 4270
  32 MAILCONTENT parse count (hard) 137 1
  85 MAILCONTENT parse count (hard) 292 0
  61 MAILCONTENT parse count (hard) 354 1
  72 MAILCONTENT parse count (hard) 472 0
  46 MAILCONTENT parse count (hard) 504 0
  24 MAILCONTENT parse count (hard) 625 0
  31 MAILCONTENT parse count (hard) 668 0

  SID USERNAME NAME VALUE HOURS_CONNECTED
———- ————— ————————- ———- —————
  75 MAILCONTENT1 parse count (hard) 1271 0
  15 parse count (hard) 4149 4270

  在oracle10g中,通过v$sess_time_model视图中对硬分析和失败分析的时间统计信息,可以知道硬分析的来源。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

相关推荐