latch介绍:
Oracle RDBMS使用了几种不同类型的锁机制。主要是latch,equeues,distributed locks和
global locks(在并行实例中执行)
1. 什么是latch
latch是低层次序列化的机制用来保护SGA中的共享数据结构。latch的执行是依赖操作系统
的,特别是关于是不是进程在等待latch和多长时间。
latch是一种lock类型,可以快速得到并释放。 Latch是用来防止超过一个进程在同
一时间执行同一段代码。和每个latch关联的是一个清楚过程。当持有latch的进程
僵死的时候将执行清楚过程。Latch有一个相关联的层次,用来防止死锁。当一个进
程请求一个层次的latch,就不能在连续请求一个相同或更低层次的latch。(除非
以nowait方式请求)
有3类latch,父latch,子latch,solitary latch。父latch和solitary latch是固定在Oracle
代码中的,子latch是在启动时分配的。
2. latch和enqueue
Enqueue是另外一种类型的锁机制。一个enqueue是个更复杂的机制,它允许并发的进程对
已知的资源有不同程度的共享。任何可以并发使用的对象,可以用enqueue来保护。一个好
的例子是表锁。我们允许不同层次的表共享比如俩个进程以共享模式所表或共享更新方式。
一个不同点是enqueue是使用OS特定锁机制获取的。一个euqneue允许用户在锁上保存一个
值,比如我们正在申请的模式。OS锁管理保持追踪锁定的资源。如果一个进程没有被对锁
授权,因为它不兼容正在申请的模式和锁被以等待的方式申请了。OS将正在申请的进程放
进一个等待队列中,这个队列是按FIFO方式服务。
另外一个不同点是latch中没有一个像enqueue一样的有序的等待队列。Latch等待者可能
使用定时器来唤醒和重试或者spin(只在多处理器中)。因为所有的等待者并发的重试(
根据定时任务),任何一个都可能得到latch,可能的一个尝试,但是却是最后一个得到。
3. 什么时候需要得到一个latch?
当和SGA中的内存结构工作的时候,一个进程获取一个latch。在和内存结构工作的时间中
将继续持有latch。当进程结束和内存结构工作的时候,latch将被删除。每个latch保护
不同结合的数据,用latch的名字标记。
Oracle使用原子指令像“测试和设置”来操作latch。进程等待执行一部分代码,但是这部分
代码的latch已被其他进程获取,那么这个进程只有等latch被释放。比如:redo allocation
latches,copy latches,archive control latch等等。基本的思想是防止并发访问共享
的数据结构。因为设置和释放latch的指令是原子的,OS保证只有一个进程能得到。因为
他是一个指令,它是非常快。Latch只在极短的时间内持有,并提供了一个清楚机制,万一
持有者僵死。这个清楚工作是由PMON进程执行。
4. latch请求模式
latch请求有俩中模式: willing-to-wait或者no wait。正常地,latch将被以
willing-to-wait模式申请。一个willing-to-wait的模式就是循环,等待,再请求直到获得
latch。在no wait模式,如果latch没有空闲,进程将发起另外一个请求,而不是等待。只
有当所有的都失败了,服务器进程才不得不等待。
willing-to-wait的latch的例子是shared pool, library cache latches。用统计信息gets
和misses统计。
no wait的例子是redo copy latch。主要用于棘手的latches。用统计信息immediate_gets
和immediate_misses统计。
5. 什么引起latch争用?
如果一个需求的latch正忙,进程请求,spin,再重试,如果仍然不可用,再spin。这个循
环重复次数使用初始化参数_SPIN_COUNT决定的。如果整个循环后,latch还是不可用,进程
必须让出cpu占有权并进入睡眠期。开始是睡眠百分之一秒。这个时间在后续的睡眠将加倍
这将导致变慢发生,结果是cpu使用率的增加。CPU的使用率是进程spinning的后果。Spinning
意味着一个进程在固定的时间后继续查找可用的latch。
5.1 latch分类
从9i开始,latch可以分成不同的类,每个类有不同的_SPIN_COUNT。默认是20000。
select indx, spin, yield, waittime
from x$ksllclass;
SQL> select indx, spin, yield, waittime
from x$ksllclass;
2
INDX SPIN YIELD WAITTIME
---------- ---------- ---------- ----------
0 20000 0 1
1 20000 0 1
2 20000 0 1
3 20000 0 1
4 20000 0 1
5 20000 0 1
6 20000 0 1
7 20000 0 1
5.2 latch free等待事件
v$session_wait中的latch free等待事件,表明进程以willing-to-wait模式获取latch失败
并spin了_SPIN_COUNT次数,然后进入了休眠。
5.3 latch miss location
保留在那个oracle内核代码发生了latch丢失信息。
col location format a30
col parent_name format a30
select location
, parent_name
, wtr_slp_count
, sleep_count
, longhold_count
from v$latch_misses
where sleep_count > 0
order by wtr_slp_count, location;
LOCATION PARENT_NAME WTR_SLP_COUNT SLEEP_COUNT LONGHOLD_COUNT
------------------------------ ------------------------------ ------------- ----------- --------------
kcbcge cache buffers chains 2779 8 0
kcbrls: kslbegin cache buffers chains 7687 365 12
kcbgtcr: kslbegin excl cache buffers chains 21050 23104 1044
kcbchg: kslbegin: call CR func cache buffers chains 25592 45 0
kcbzwb cache buffers chains 26248 37769 540
kqrpre: find obj row cache objects 50025 68746 0
kqrpfl: not dirty row cache objects 62093 43359 0
kcbchg: kslbegin: bufs not pin cache buffers chains 112667 134624 0
ned
WTR_SLP_COUNT - 等待者睡眠的次数。
SLEEP_COUNT - 请求latch导致睡眠的次数。
LONGHOLD_COUNT - 在等待者睡眠整个期间,进程持有latch的次数。
6. 如何辨别latch争用
V$LATCH
V$LATCHHOLDER
V$LATCHNAME
"willing-to-wait" Hit Ratio=(GETS-MISSES)/GETS
"no wait" Hit Ratio=(IMMEDIATE_GETS-IMMEDIATE_MISSES)/IMMEDIATE_GETS
这些值应该接近1。如果不是,根据latch的名字调优。
6.1 AWR 报表中latch的信息
6.1.1 latch的总体情况。
Instance Efficiency Percentages (Target 100%)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Buffer Nowait %: 100.00 Redo NoWait %: 100.00
Buffer Hit %: 99.60 In-memory Sort %: 100.00
Library Hit %: 98.02 Soft Parse %: 93.94
Execute to Parse %: 57.81 Latch Hit %: 98.26
Parse CPU to Parse Elapsd %: 98.40 % Non-Parse CPU: 97.86
latch hit% - 表示latch命中率。
"willing-to-wait" Hit Ratio=(GETS-MISSES)/GETS
"no wait" Hit Ratio=(IMMEDIATE_GETS-IMMEDIATE_MISSES)/IMMEDIATE_GETS
6.1.2 top 5等待事件
Top 5 Timed Events
~~~~~~~~~~~~~~~~~~ % Total
Event Waits Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
latch free 2,048,146 3,805 31.39
CPU time 3,613 29.81
enqueue 88,999 2,631 21.71
db file sequential read 151,409 656 5.41
SQL*Net break/reset to client 213,028 506 4.17
如果latch free进入top 5等待事件,需要关注。
6.1.3 latch的明细的信息:
Latch Activity for DB: DBS Instance: TESTDB Snaps: 67875 -67876
->"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
------------------------ -------------- ------ ------ ------ ------------ ------
Consistent RBA 864,907 0.0 0.0 0 0
FAL request queue 53 0.0 0 0
FAL subheap alocation 4 0.0 0 0
FIB s.o chain latch 20 0.0 0 0
FOB s.o list latch 9,957 0.0 0 0
SQL memory manager latch 1 0.0 0 300 0.0
SQL memory manager worka 74,661 0.0 0 0
active checkpoint queue 3,187,342 1.6 0.0 0 0
alert log latch 1,560 0.0 0 0
archive control 167 0.0 0 0
archive process latch 65 0.0 0 0
begin backup scn array 1 0.0 0 0
cache buffer handles 21,551 0.0 0 0
cache buffers chains 454,626,669 0.0 0.0 10 1,779,732 0.0
cache buffers lru chain 605,800 0.0 0.0 0 2,021,496 0.0
channel handle pool latc 10,848 0.0 0.0 0 0
channel operations paren 16,942 0.0 0.0 0 0
checkpoint queue latch 1,140,976,890 0.0 0.0 0 140,838 0.0
undo global data 434,079,118 3.2 0.1 3624 0
latch - latch名字
get requests - 以willing-to-wait模式请求latch次数
Pct Get miss - 以willing-to-wait模式请求latch次数时必须等待的百分比
Avg Slps/Miss - 以willing-to-wait模式请求latch,然后一直在等待直至sleeps,平均每次等待产生睡眠的比例。
Wait Time(s) - 等待的总时间(s)
NoWait Requests - 以no-wait模式请求的次数
Pct NoWait Miss - 以no-wait模式请求的没有成功的次数所占用的百分比。
6.1.4 latch的分解信息:
Latch Sleep breakdown for DB: TESTDB Instance: TESTDB Snaps: 67875 -67876
-> ordered by misses desc
Get Spin &
Latch Name Requests Misses Sleeps Sleeps 1->4
-------------------------- -------------- ----------- ----------- ------------
undo global data 434,079,118 13,791,770 1,625,558 12511367/999
134/229060/5
2209/0
row cache enqueue latch 50,931,324 12,107,941 1,582 12106361/157
8/2/0/0
enqueues 36,426,041 10,113,124 4,838 10108419/457
5/127/3/0
row cache objects 50,987,843 4,915,932 286,380 4660648/2286
28/22776/388
0/0
transaction allocation 222,110,544 1,299,459 133,733 1240084/3043
1/12467/1647
7/0
enqueue hash chains 47,365,639 550,422 337 550085/337/0
/0/0
latch - latch名字
get requests - 以willing-to-wait模式请求latch次数
misses - 请求latch时必须等待的次数
sleeps - 请求latch未能正常获取,导致等待直至sleeps的次数。
Spin &Sleeps 1->4 - 以willing-to-wait模式请求latch,在第一次尝试时失败,但是在spin时成功的次数。第1->4次休眠的次数。
6.1.4 latch的来源信息:
Latch Miss Sources for DB: TESTDB Instance: TESTDB Snaps: 67875 -67876
-> only latches with sleeps are shown
-> ordered by name, sleeps desc
NoWait Waiter
Latch Name Where Misses Sleeps Sleeps
------------------------ -------------------------- ------- ---------- --------
cache buffers chains kcbget: exchange rls 0 1 0
cache buffers chains kcbzib: finish free bufs 0 1 0
cache buffers chains kcbgtcr: kslbegin shared 0 1 0
cache buffers chains kcbgtcr 0 1 0
enqueue hash chains ksqgtl3 0 190 219
enqueue hash chains ksqrcl 0 145 114
enqueue hash chains ksqcnl 0 4 6
enqueues ksqgel: create enqueue 0 2,582 2,718
enqueues ksqdel 0 2,253 2,108
enqueues ksqies 0 3 12
library cache kglic 0 22 120
shared pool kghupr1 0 11 278
shared pool kghfre 0 2 6
transaction allocation ktcxbr 0 133,733 133,733
undo global data ktusm_stealext: KSLBEGIN 0 1,606,765 ########
undo global data ktusmupst: KSLBEGIN 0 6,658 8,743
undo global data ktucmt: ktugd_cuux 0 5,907 5,182
undo global data ktusmasp: ktugd_tuux 0 2,910 4,862
undo global data ktusmasp: ktugd_suux 0 2,892 4,296
undo global data ktugnb: ktugd_tuux 0 292 300
undo global data kturdc: KSLBEGIN 0 148 77
undo global data ktudba: KSLBEGIN 0 81 1,536
undo global data ktugnb: ktugd_cuux 0 9 11
undo global data ktudnx:child 0 7 196
undo global data ktubnd:child 0 2 85
undo global data ktucof: at start 0 2 1
latch - latch名字
where - latch等待的位置
NoWait misses - 以no-wait模式请求latch时失败的次数
sleeps - 以no-wait模式请求latch时,导致等待直至sleeps的次数。
Waiter Sleeps - 记录进程在此内核位置request对应latch的次数
7. 有用的SQL Scripts得到latch信息
/*
** Display System-wide latch statistics.
*/
column name format A32 truncate heading "LATCH NAME"
column pid heading "HOLDER PID"
select c.name,a.addr,a.gets,a.misses,a.sleeps,
a.immediate_gets,a.immediate_misses,b.pid
from v$latch a, v$latchholder b, v$latchname c
where a.addr = b.laddr(+)
and a.latch# = c.latch#
order by a.latch#;
/*
** Given a latch address, find out the latch name.
*/
column name format a64 heading 'Name'
select a.name from v$latchname a, v$latch b
where b.addr = '&addr'
and b.latch#=a.latch#;
/*
** Display latch statistics by latch name.
*/
column name format a32 heading 'LATCH NAME'
column pid heading 'HOLDER PID'
select c.name,a.addr,a.gets,a.misses,a.sleeps,
a.immediate_gets,a.immediate_misses,b.pid
from v$latch a, v$latchholder b, v$latchname c
where a.addr = b.laddr(+) and a.latch# = c.latch#
and c.name like '&latch_name%' order by a.latch#;
9. DBA关注的latch
BUFFER CACHE LATCHES: 有俩个主要的latch来保护buffer cache的数据块。这俩个
latch的争用经常发生在database过高的IO。我们可以通过调节init.ora的参数来减少latch
的争用。
Cache buffers chains latch: 只要buffer cache的中块被访问,这个latch就被获取
减少Cache buffers chains latch需要减少逻辑IO,这可以通过优化和最小化SQL的IO需
求。过高的IO可能是一个热块的迹象(意味着一个块被过度访问)。
Cache buffers LRU chain latch:
Cache buffers LRU chain latch这个latch是引入一个新块到buffer cache中和写一个
buffer回到磁盘,特别是扫描LRU(最近使用)链,其中buffer cache包含脏块。
减少cache buffers LRU chain latch需要增加buffer cache的大小,这样就减少新块引入
的几率。可以通过改参数db_cache_size来增大buffer cache。多个buffer pool可以帮助
减少这个latch的争用。你可以通过DB_BLOCK_LRU_LATCHES/_DB_BLOCK_HASH_BUCKETS来增加
cache buffer lru chain。
REDOLOG BUFFER LATCHES: 有俩种reco buffer latches,the redo allocation latch 和
the redo copy latch。redo allocation latch在buffer中分配空间时必须获得。如果重做
日志的条目比LOG_SMALL_ENTRY_MAX_SIZE参数大。已获取redo allocation latch的会话可
能拷贝条目到重做buffer中,如果日志的条目比LOG_SMALL_ENTRY_MAX_SIZE大,那么会话将
立即释放redo allocation latch并请求redo copy latch来拷贝条目。只有一个redo
allocation latch,但是也有最大到LOG_SIMULTANEOUS_COPIES的allocation latches。
Redo allocation latch:
这个latch控制在重做日志buffer中的重做条目的空间分配。一个实例只有一个redo
allocation latch。
可以通过增加log_buffer来减少log buffer的使用,从而减少redo allocation latch的争
用。也可以通过nologging减少日志文件的负载。
Redo copy latch:
这个latch用来写重做记录到重做日志buffer中。这个latch在单cpu和多cpu系统中被等待。
在多cpu系统中,可以增加LOG_SIMULTANEOUS_COPIES来减少争用。
LIBRARY CACHE
Library cache latch:
Libary cache latch保护缓存的SQL statements和shared pool/library cache中的对象定
义。为了增加一个新statement到library cache中Library cache latch必须被获取。在解
析的时候,Oracle在libraray cache中查找一个匹配的statement。如果没有找到,然后
Oracle将解析SQL statement,获取library cache latch,并增加新的SQL。
减少这个latch的争用的第一资源是保证应用尽可能地重用SQL statement。如果有可能,在
应用中使用绑定变量。错过这个latch也是一个迹象,应用在过度地解析SQL,并可能经历太
多解析CPU。
参数_KGL_LATCH_COUNT控制library cache latch的数目。默认值应该足够了,但是如果能
解决这个latch争用,建议可以增加这个值。默认值是比CPU_COUNT大的下一个素数。这个值
不能超过66.
Library cache pin latch:
The library cache pin latch 当一个library cache中的statement重新执行时必须获得。
错过这个latch发生在过度地SQL执行。
为减少library cache pin latch负载能做的不多,尽管使用私有的同义词而不是使用公共
的同义词,或者使用直接的对象引用比如OWNER.TABLE也许有帮助。
SHARED POOL RELATED LATCHES
Shared pool latch:
在分配和释放shared pool中的内存时,Shared pool latch是用来保护重要的操作。如果一
个应用使用常量(非共享)SQL,将严重限制可扩展性和吞吐量。解析一个新的SQL
statement的成本是很高的,包括CPU的要求和library cachehe/shared pool latches获取
和释放的次数。
减少shared pool latch的方法是避免硬分析,解析一次,执行多次。消除常量的SQL也是非
常有用的。
Row cache objects latch:
这个latch起作用是在用户进程试图访问缓存的数据词典的值。
这个latch上的争用不是很普遍,减少这个latch争用的方法是增加shared pool的大小。
10. 调整_SPIN_COUNT
SPIN_COUNT控制进程在睡眠之前尝试多少次去获取latch。这个基本意思是进程在一个CPU紧
凑的循环中不断地尝试SPIN_COUNT次去获得latch。在一个单cpu系统中,如果一个进程想获
取一个latch,但是这个latch被其他进程持有,这个进程将释放CPU并睡眠很短的时间,然
后重试。然而,在一个多处理器(SMP)系统中,持有latch的进程运行在其他cpu上,并且
可能在很少的指令后就释放latch(latch通常持有很短时间)。
更改SPIN_COUNT的值可能影响性能。如果使用很大的值,latch将比小的值更快地被获得。
然而你将使用更多的CPU时间spinning来获取latch。在latch上的Spinning消耗CPU,所以如
果你增大这个值,CPU的使用率将增高。如果你的CPU是100%,你的系统关注吞吐量,而不是
响应时间,你可以考虑减少SPIN_COUNT。如果CPU资源很宽松,那么你可以增大这个值,如
果没有空余的CPU容量的话,那么就减少这个值。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25105315/viewspace-752715/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/25105315/viewspace-752715/