Oracle latch竞争总结(一)

    在Oracle中,Latch的概念是非常重要的,v$latch表的每一行包括了对不同类型latch的统计,每一列反映了不同类型的latch请求的活动情况。不同类型的latch请求之间的区别在于,当latch不可立即获得时,请求进程是否继续进行。按此分类,latch请求的类型可分为两类:willing-to-wait和immediate。

    latch free,相信跟大家并不陌生,在v$session_wait和Top5中会出现,当然出现类似的内容,就证明Latch产生了竞争,并且已经影响到了你的系统性能。

    首先我们来列举一下Latch出现竞争的几种常见情况:
        1、cache buffers chains
       2、shared pool
       3、library cache

    当然,我们需要一个一个来进行解释和分析,首先我们先来说下cache buffers chains


关于LATCH产生得解释:

Blocks in the buffer cache are placed on linked lists(cache buffer chains) which hang off a hash table.
The hash chain that a block is placed on is based on the DBA and CLASS of the block. Each hash chain is
protected by a single child latch. Processes need to get the relevant latch to allow them the scan a hash chain for a buffer so that the linked list does not change underneath them.

Contention for these latches can be caused by:

- Very long buffer chains.
- very very heavy access to the same blocks.

现在对数据库的实际操作过程:

SQL> select count(*)
  from v$latch_children
where misses > 0
   and name = 'cache buffers chains';

COUNT(*)
----------
2048

SQL> select addr, name, misses
  from v$latch_children
where misses > 0
   and name = 'cache buffers chains'
order by misses desc;
ADDR NAME MISSES

-------- ---------------------------------------------------------------- ----------
69CC28BC cache buffers chains 1591
69A3CF1C cache buffers chains 1591
69CBDDFC cache buffers chains 1589
69B92DFC cache buffers chains 1586
69C5DEBC cache buffers chains 1585
69AB0354 cache buffers chains 1585
69A70F9C cache buffers chains 1585
69A81F54 cache buffers chains 1585

SQL> select bh.addr, obj.name obj_name, bh.tch touch
  from x$bh bh,
       sys.file$ f,
       v$datafile fl,
       sys.obj$ obj,
       sys.ts$ ts
where fl.file# = f.file#
   and bh.file# = fl.file#
   and obj.dataobj# = bh.obj
   and bh.ts# = ts.ts#
   and bh.HLADDR in(
     select addr from v$latch_children where misses>0 and name='cache buffers chains'
   )
   and bh.tch > 0
order by bh.tch desc;

ADDR OBJ_NAME                           TOUCH
-------- ------------------------------ ----------
B6FD3078 IDX_GCTID_IUID_GM634           24
B6FD3078 REG_LOG                        8
B6FD2F9C AGENT_CARD_TYPE                7
B6FD3078 RESELLER_AGENTCARD_PRICE       6
B6FD3078 RESELLER_LOG                   6
B6FD3078 IDX_ACL_AGENTID_LOGTIME        6
B6FD3078 RESELLER_LOG                   6

就是上面涉及到的这些对象,造成LATCH

SQL> select COUNT(*)
  from x$bh bh, sys.file$ f, v$datafile fl, sys.obj$ obj, sys.ts$ ts
where fl.file# = f.file#
   and bh.file# = fl.file#
   and obj.dataobj# = bh.obj
   and bh.ts# = ts.ts#
   and bh.HLADDR = [x$bh.addr] --物理地址
   and bh.tch > 0;

COUNT(*)
----------
51


一段文档资料:

Under 8.0, the default was next_prime(db_block_buffers/4), and the
number of _db_block_hash_latches was 1:1 with the number of buckets.
Under 8i, the world changed a lot. The default number of hash buckets
is 2 * db_block_buffers, but the latches work differently. It's
really not necessary to have one latch per hash chain, so, Oracle made
them a pooled resource. When you need to interrogate a hash chain,
you grab a latch from the pool and assign it to a hash chain. That
prevents anyone else from modifying the chain or it's contents while
your process is using it. So, in 8i, the size of the latch pool is
dynamic but is set to 1024 for most cases. It's smaller for very
small buffer caches and larger for very large buffer caches. The
formula is:
if (db_block_buffers < 2052) then
db_block_hash_latches = 2^trunc(log(2,db_block_buffers - 4) - 1)
else if(2052 =< db_block_buffers <= 131075) then
db_block_hash_latches = 1024
else if(db_block_buffers > 131075)
db_block_hash_latches = 2^trunc(log(2,db_block_buffers - 4) - 6)
end if

So, under 8i, you probably don't need to touch _db_block_hash_buckets,
as 2 * db_block_buffers is almost certainly more than adequate. And
unless you're dealing huge numbers of concurrent users and a
relatively small buffer cache, you probably don't need to mess with
_db_block_hash_latches, either.

增大 _db_buffer_hash_latches 可以更快速的查找到 blocks 并且降低 cache buffer chains 等待
我的操作系统是9I,db_block_buffers 为DB_CACHE_SIZE,如果我调整此参数,那么我应该是采取
db_block_hash_latches = 2^trunc(log(2,DB_CACHE_SIZE - 4) - 6)

SQL> show parameter db_cache_size;

NAME TYPE VALUE
------------------------------------ -------------------------------- ------------------------------
db_cache_size big integer 1073741824

SQL> select name,
       value,
       decode(isdefault, 'TRUE', 'Y', 'N') as "Default",
       decode(ISEM, 'TRUE', 'Y', 'N') as SesMod,
       decode(ISYM, 'IMMEDIATE', 'I', 'DEFERRED', 'D', 'FALSE', 'N') as SysMod,
       decode(IMOD, 'MODIFIED', 'U', 'SYS_MODIFIED', 'S', 'N') as Modified,
       decode(IADJ, 'TRUE', 'Y', 'N') as Adjusted,
       description
  from ( --GV$SYSTEM_PARAMETER
        select x.inst_id as instance,
                x.indx + 1,
                ksppinm as name,
                ksppity,
                ksppstvl as value,
                ksppstdf as isdefault,
                decode(bitand(ksppiflg / 256, 1), 1, 'TRUE', 'FALSE') as ISEM,
                decode(bitand(ksppiflg / 65536, 3),
                       1,
                       'IMMEDIATE',
                       2,
                       'DEFERRED',
                       'FALSE') as ISYM,
                decode(bitand(ksppstvf, 7), 1, 'MODIFIED', 'FALSE') as IMOD,
                decode(bitand(ksppstvf, 2), 2, 'TRUE', 'FALSE') as IADJ,
                ksppdesc as description
          from x$ksppi x, x$ksppsv y
         where x.indx = y.indx
           and substr(ksppinm, 1, 1) = '_'
           and x.inst_id = USERENV('Instance'))
where name = '_db_block_hash_latches'
order by name;

NAME VALUE
------------------------------ ---------------
_db_block_hash_latches 2048

SQL> select power(2,trunc(log(2,1073741824 - 4) - 6)) from dual;

POWER(2,TRUNC(LOG(2,1073741824-4)-6))
-------------------------------------
8388608

    总得来说,LATCH产生得原因还是从应用入手,不要期望通过调整某些参数达到立杆见影的效果,热块、大的逻辑读和物理读,全表扫描都是会导致产生LATCH得原因。

你可能感兴趣的:(oracle,sql,cache,F#,活动)