a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 107|回复: 1

[综合] Oracle辅导:Oracle中的Latch和latch冲突

[复制链接]
发表于 2012-8-4 13:54:49 | 显示全部楼层 |阅读模式
引言   Oracle Rdbms应用了各种不同类型的锁定机制,latch即是其中的一种,本文将集中介绍latch(闩)的概念,理解latch的实现方法并说明引起latch冲突的原因。( P/ L, x. y/ I# L; U# i, V, G# L
  什么是latch
$ \8 Y0 A8 F9 ]  P1 R! _  Latch是用于保护SGA区中共享数据结构的一种串行化锁定机制。Latch的实现是与操作系统相关的,尤其和一个进程是否需要等待一个latch、需要等待多长时间有关。: z) b+ e& U5 |4 h
  Latch 是一种能够极快地被获取和释放的锁,它通常用于保护描述buffer cache中block的数据结构。与每个latch相联系的还有一个清除过程,当持有latch的进程成为死进程时,该清除过程就会被调用。Latch 还具有相关级别,用于防止死锁,一旦一个进程在某个级别上得到一个latch,它就不可能再获得等同或低于该级别的latch。
# u" b* P8 C0 y  Latch与Enqueue(队列), I2 k+ s  N& }/ R9 z1 y
  Enqueue 是Oracle使用的另一种锁定机制,它更加复杂,允许几个并发进程不同程度地共享某些资源。任何可被并发使用的对象均可使用enqueue加以保护。一个典型的例子是表的锁定,我们允许在一个表上有不同级别的共享。与latch不同之处在于,enqueue是使用操作系统特定的锁定机制,一个 enqueue允许用户在锁上存贮一个标记,来表明请求锁的模式。操作系统lock manager跟踪所有被锁定的资源,如果某个进程不能获取它所请求的那种锁,操作系统就把请求进程置于一个等待队列中,该队列按FIFO原则调度,而在 latches中是没有象enqueue中排序的等待队列,latch等待进程要么使用定时器来唤醒和重试,要么spin(只用于多处理器情况下)。
# b! @% F/ l) E  何时需要latch  Q& h! D3 c8 ?4 L4 {% \
  当一个进程准备访问SGA中的数据结构时,它就需要获得一个latch。当进程获得latch后,它将一直持有该latch直到它不再使用此数据结构,这时latch才会被释放。可通过latch名称来区分它所保护的不同数据结构。2 [" H' q& Y- M% @
  Oracle 使用元指令对latch进行操作, 当所需的latch已被其他进程持有时,执行指令进程将停止执行部分指令,直到该latch被释放为止。从根本上讲,latch防止并发访问共享数据结构,由于设置和释放latch的指令是不可分割的,操作系统就可以保证只有一个进程获得latch,又由于这只是单条指令,所以执行速度很快。latch 被持有的时间是很短,而且提供了当持有者不正常中断时的清除机制,该清除工作是由Oracle后台进程PMON来完成的。2 }% f! I* V: z+ p( s
  什么导致latch冲突! T  N" f; d% L$ h: W* W( g, @
  Latch 保护SGA中的数据结构被多个用户同时访问,如果一个进程不能立即得到所需latch,它就必须等待,这就导致了CPU的额外负担和系统的速度降低。额外的CPU使用是进程‘spining’导致的,‘spining’是指进程定时地重复尝试获取latch,在连续两次之间,进程处于休眠状态,在得到 latch之前,spining过程将重复进行下去。, Q, w/ R6 F; r9 b
  如何标识内部latch的冲突+ t8 l9 g: K  ]) D2 a
  Server manager monitor是一个相当有用的来监视latch等待、请求和冲突的工具。也可查询相关的数据字典表:v$latch, v$latchholder, v$latchname。
" k$ e- h9 X$ }6 w2 S5 k  v$latch 表的每一行包括了对不同类型latch的统计,每一列反映了不同类型的latch请求的活动情况。不同类型的latch请求之间的区别在于,当latch 不可立即获得时,请求进程是否继续进行。按此分类,latch请求的类型可分为两类:willing-to-wait和immediate。# d. j5 D/ n5 q7 r$ `; w* H
  Willing-to-wait : 是指如果所请求的latch不能立即得到,请求进程将等待一很短的时间后再次发出请求。进程一直重复此过程直到得到latch。
7 k6 ^: A$ @5 y( n2 H+ V4 K  Immediate:是指如果所请求的latch不能立即得到,请求进程就不再等待,而是继续执行下去。: I6 V) n( ~* y- i4 c2 W1 s
  在v$latch中的以下字段反映了Willing-to-wait请求:
' J2 x! C  f" u# l2 E  GETS---成功地以Willing-to-wait请求类型请求一个latch的次数。
! y6 c$ g8 \! {# D  v$ a  MISSES---初始以Willing-to-wait请求类型请求一个latch不成功的次数。0 U* w4 E" J0 L- o* k
  SLEEPS---初始以Willing-to-wait请求类型请求一个latch不成功后,进程等待获取latch的次数。
, V/ P7 i/ |& j% f, X( Y  在v$latch中的以下字段反映了Immediate类请求:0 M% b( b* V: u) g3 K7 g" _
  IMMEDIATE_GETS---以Immediate请求类型成功地获得一个latch的次数。4 [9 v, V* V' O/ ]# I
" Y7 k8 y% K" `2 Z; z: ~( y% @* ~
  IMMEDIATE_MISSES---以Immediate请求类型请求一个latch不成功的次数。
回复

使用道具 举报

 楼主| 发表于 2012-8-4 13:54:50 | 显示全部楼层

Oracle辅导:Oracle中的Latch和latch冲突

</p>  我们可以通过对v$latch, v$latchholder, v$latchname的查询获得有关latch信息,例如:
! ?+ t+ J' a7 N3 p  /* 已知一个latch地址,找到latch名字 */
4 j& X, Z7 R# v. K( h/ A  col name for a406 o# M1 s  S/ M1 s9 r  W
  select a.name from v$latchname a, v$latch b
2 {8 l2 l( U) ~) W8 M8 `  where b.addr = '&addr') k! l$ [) l  }- X
  and b.latch#=a.latch#;$ `. s( s" \+ _
  /* 显示系统范围内的latch统计 */% l" U% C0 c, H% m( _* p+ ]. @! f
  column name format A32 truncate heading "LATCH NAME"  e/ s1 x2 E1 P8 ?! l
  column pid heading "HOLDER PID"
" q8 g' Q; e% n% i8 ?( h7 J& m  select c.name,a.addr,a.gets,a.misses,a.sleeps,4 |7 p) [1 i8 }8 C" z
  a.immediate_gets,a.immediate_misses,b.pid
. |5 E4 a5 x/ q0 @2 f/ Y  from v$latch a, v$latchholder b, v$latchname c- @8 K( b$ a  g4 @  L# N+ ~
  where a.addr = b.laddr(+)
6 w( ~7 Z: s$ m9 l. C7 R# m  and a.latch# = c.latch#: I8 d" a. q! S6 Q! o5 D: g3 i$ y
  order by a.latch#;
' T2 F  Q: O: U7 x  /* 由latch名称显示对latch的统计 */5 m, {6 P# J6 _' {
  select c.name,a.addr,a.gets,a.misses,a.sleeps,, r0 Y8 Y+ l7 E
  a.immediate_gets,a.immediate_misses,b.pid
% |' ]" P- {+ w1 D8 L$ B  from v$latch a, v$latchholder b, v$latchname c3 b) C- W* T0 j. V! Y  c6 C
  where a.addr = b.laddr(+) and a.latch# = c.latch#
) P7 J- y' d0 N9 y6 j& e. F  and c.name like '&latch_name%' order by a.latch#;2 e9 e+ u& Q* v
  latch有40余种,但作为DBA关心的主要应有以下几种:
) o8 I  B2 ^2 B0 U, ~  Cache buffers chains latch: 当用户进程搜索SGA寻找database cache buffers时需要使用此latch。" |6 D: q- G' ^: P% d5 |
  Cache buffers LRU chain latch: 当用户进程要搜索buffer cache中包括所有 dirty blocks的LRU (least recently used) 链时使用该种latch。; d2 {4 o" d+ ^0 C6 E# C
  Redo log buffer latch: 这种latch控制redo log buffer中每条redo entries的空间分配。
+ m8 ^7 J6 P' `$ w, x. v+ r  Row cache objects latch: 当用户进程访问缓存的数据字典数值时,将使用Row cache objects latch。* e4 y6 i' ?0 b$ f7 q; ~
  下 面我们将着重介绍一下如何检测和减少redo log buffer latch的冲突。对redo log buffer的访问是由redo log buffer latch来控制的,这种latch有两种类型, redo allocation latch和redo copy latch。
3 i' m; `! R* M- o7 B( m  Redo allocation latch控制redo entries在redo log buffer中的空间分配。Oracle的一个用户进程只有得到redo allocation latch后才能为redo entries在redo log buffer中分配空间,又由于一个instance只有一个redo allocation latch,所以一次只有一个用户进程在buffer中分配空间。当用户进程获得latch后,首先为redo entry分配空间,然后进程继续持有latch并拷贝entry到buffer中,这种拷贝称为“在redo allocation latch上的拷贝”(copying on the redo allocation latch),拷贝完毕后,用户进程释放该latch。
& ~- j5 M) U- w% X& L  一个“在redo allocation latch上的拷贝”的redo entry的最大值是由初始化参数LOG_SMALL_ENTRY_MAX_SIZE定义的,根据操作系统的不同而不同。  L2 w0 N( o+ A2 i0 y& u
  Redo Copy Latch只应用于多CPU的系统。在多CPU的instance中,如果一个redo entry太大,超过了LOG_SMALL_ENTRY_MAX_SIZE定义值,则不能进行“在redo allocation latch上的拷贝”, 此时用户进程必须获取redo copy latch。一个instance中可以有多个redo copy latch,其数目由初始参数LOG_SIMULTANEOUS_COPIES决定,缺省值为CPU数目。& |! m$ k% L: W( w" w! X5 @& G
  在单CPU情况下,不存在redo copy latch,所有的redo entry无论大小, 都进行“在redo allocation latch上的拷贝”。
+ W7 I1 p  W) `8 ~9 g; z7 V  对redo log buffer的过多访问将导致redo log buffer latch的冲突,latch冲突将降低系统性能,我们可通过如下查询来检测这种latch冲突:
4 Y' i# |9 G) L* Y' ]  col name for a40
  ^: D: ~4 |/ J2 Y$ H' g5 {  SELECT ln.name,gets,misses,immediate_gets,immediate_misses
/ Y. X- d+ b3 n1 r1 @  FROM v$latch l,v$latchname ln
# w; Z% y" y3 b2 S, ?5 d  WHERE ln.name IN('redo allocation','redo copy') AND ln.latch#=l.latch#
2 D; Y5 F. x8 Q7 p; g6 V, ~! d  /
$ g/ ]4 |" J. V  若misses与gets的比例超过1%或immediate_misses与(immediate_gets+immediate_misses)比例超过1%时,应考虑采取措施减少latch的冲突。
8 |  y* P: u# t  大 多数的redo log buffer latch冲突是在多个CPU情况下,两个或多个Oracle进程试图同时得到相同的latch发生的。由于一个instance只有一个redo allocation latch,为减少redo allocation latch的冲突,应减少单个进程持有latch的时间,这可以通过减小初始参数LOG_SMALL_ENTRY_MAX_SIZE以减小redo entry的数目和大小来实现。如果观察到有redo copy latch冲突,可以通过增大LOG_SIMULTANEOUS_COPIES 初始参数来加大latch数目,其缺省值为CPU数目,最大可增大到CPU数目的两倍。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-15 10:09 , Processed in 0.143583 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表