星期四, 五月 24, 2007

Oracle Latch internals随笔一

仅以本文来总结和复习Oracle Interals,并结合实际工作中的经验,让自己对Oracle的Latch有一个更清楚的认识。
首先,我们要知道什么是Latch,用Latch的目的是什么。下面我们就来探讨下Latch的相关概念及内部信息。Latch是用来保护内存资源的一个轻量级的锁。主要目的有两点:
1、 串行化访问(To serialize access),保护SGA中的数据结构和共享内存的分配。
2、 串行化执行(To serialize execution),防止同时执行特定重要代码,防止数据结构的损坏.
借用排他性的Latch,进程能够阻止其他进程对有这个Latch保护的数据结构的读和写。由此看出Latch对内存数据结构提供一种互斥访问机制。在没有一致性读机制的情况下,先期读取者会阻止修改者。在没有Shared Latch在相关平台的情况下,先期读取者也会阻止其他访问者。如果Latch的持有者进程意外终止,那么会有一个相关的清除机制会处理这个情况。通常这个工作是有PMON进程来restore和clean up。而其中关于这个Latch的undo information一般典型的存在SGA状态对象(SGA state objects)中。常见的Latch一般有shared pool latch、session allocation latch(负责保护在variable SGA 中的session state object的分配)、cache buffers lru chain latch(负责保护在LRU lists中Buffer headerd 分配和移动)。
Oracle server允许对象同时以共享的模式区使用队列(equeue)。而Latch用来保护大的数据结构或者被高频率访问的结构,由此Latch都是排它性的,并且存在时间很短的特点,对性能和并发用户的可用性的影响降到最低。在请求enqueue时,如果一个进程没有被授权,那一般是因为请求模式和现有的模式不够兼容,O/S就会把请求进程放在一个FIFO模式的等待队列(wait queue)中。而对于Latch的请求,Latch waitesr一直按顺序提交请求。
特殊情况下,Oracle server请求在一个大数据结构(large stucture)上的Latch,在一个相对长的时间内为了安全访问以及锁定小子数据结构(smaller sub-structure)时,需要利用复杂的像enqueues的锁机制。比如,在更新一个row时,Oracle server会得到一个cache buffers chains latch去搜索hash chain,此过程主要是为了在data buffer中找到那个data block。然后pins住这个block,然后释放cache buffers chains latch。然后Oracle server会lock这个数据块中的row,修改行,然后unpins这个block。到目前为止,这个row仍然被lock in exlusive mode至到事务结束。Lock row不会影响block中的其他数据和在cahe中的其他buffers。
虽然Latch的使用是在操作系统级别,但是平常是作为一个内存位(single memory location)去操作。Latch free时为0,Latch not free时为一个非0。这个内存位经常增加到32个字节,为了避免在硬件级别上的Cache line竞争。Latch被设计成一个fast和inexpensive的锁。Latch真实操作依靠于操作系统。对于shared latches不是很广泛的被使用。这种类型的锁主要是用于高级队列代码(Advance Queuing code)。存在一种机制可以让进程什么时候,以如何方式获得Latch,而不发生死锁。
Latch可以是独立Latch(solitary Latch),也可以是Latch集(Latch set)。Latch set有父Latch和多个子Latch组成。独立Latch和父Latch是静态分配的,而子Latch是动态分配的。父Latch和子Latches有相同的名字。父Latch做为控制Latch(master latches)。Latch具有级别的特性(Levels),利用这个优先级可以避免死锁。父Latch在数量上是固定的,应该在相关代码中所定义。从Oracle9R2开始,有了不同类型的父Latch,但每个类型只有一个父latch。子Latch是依据相关参数(比如_CPU_COUNT)设定或者默认值动态分配的。父Latch一般只作为聚合统计之用,但library cache是个例外。如Solitary Latches:shared pool,redo allocation;PAR Latches:cache buffers lru chain、cache buffers chains;PR2 Latches:library cache。当一个进程请求no-wait模式的latch时,该latch的优先级编号必须和它当前已经持有的latch的优先级编号相同。当一个进程请求willing-to-wait模式的latch时,该latch的优先级编号必须比它当前已经持有的latch的优先级编号要大。
Latch是在操作系统中以某种方式来执行。如果一个latch真在被占用,那边requestor spins and tries agin,in a loop up to _SPIN_COUNT number of time。for single CPU systems _SPIN_COUNT=1。如果在一个单cpu的环境下,一个进程持有一个Latch,但它没有释放这个latch,那就没有必要去spin了。否则,当cpu的数量大于1,那么_SPIN_COUNT的默认值是2000。

-------------------------------------------------待续-----------------------------------------------------------------------

没有评论: