oracle 锁和闩_笔记13:闩的问题
闩
闩(latch)是轻量级的串行化设备,用于协调对共享数据结构、对象和文件的多用户访问。
闩就是一种锁,设计为只保持极短的一段时间(例如,修改一个内存中数据结构所需的时间)。闩用于保护某些内存结构,如数据库块缓冲区缓存或共享池中的库缓存。一般会在内部以一种“愿意等待”(willing to wait)模式请求闩。这说明,如果闩不可用,请求会话会睡眠很短的一段时间,并在以后再次尝试这个操作。还可以采用一种“立即”(immediate)模式请求其他闩,这与SELECT FOR UPDATE NOWAIT的思想很相似,说明这个进程会做其他事情(如获取另一个与之相当的空闲闩),而不只是坐而等待这个闩直到它可用。由于许多请求者可能会同时等待一个闩,你会看到一些进程等待的时间比其他进程要长一些。闩的分配相当随机,这要看运气好坏了。闩释放后,紧接着不论哪个会话请求闩都会得到它。等待闩的会话不会排队,只是一大堆会话在不断地重试。
Oracle使用诸如“设计和设置”(test and set)以及“比较和交换”(compare and swap)之类的原子指令来处理闩。由于设置和释放闩的指令是原子性的,尽管可能有多个进程在同时请求它,但操作系统本身可以保证只有一个进程能测试和设置闩。指令仅仅是一个指令而已,它执行得可能非常快(但整个闩算法本身是许多个CPU指令)。闩只保持很短的时间,而且提供了一种清理机制,万一某个闩持有者在抢救无效有闩时异常地“死掉了”,就能执行清理。这个清理过程由PMON执行。
队列锁(enquere)是一种更复杂的串行化设备,例如,在更新数据库表中的行时就会使用队列锁。与闩的区别在于,队列锁允许请求者“排队”等待资源。对于闩请求,请求者会话会立即得到通知是否得到了闩。而对于队列锁,请求者会话会阻塞,直至真正得到锁。
因此,队列锁没有闩快,但是它确实能提供闩所没有的一些功能。可以在不同级别上得到队列锁,因此可以有多个共享锁以及有不同程度共享性的锁。
闩“自旋”
关于闩还要了解一点:闩是一种锁,锁是串行化设备,而串行化设备会妨碍可扩展性。如果你的目标是构建一个能在Oracle环境中很好地扩展的应用,就必须寻找合适的方法和解决方案,尽量减少所需执行的闩定的量。
有些活动尽管看上去世很简单(如解析一条SQL语句),也会为共享池中的库缓存和相关结构得到并释放数百个或数千个闩。如果我们有一个闩,可能会有另外某个人在等待这个闩。而当我们想要得到一个闩时,也许我们自己也必须等待。
等待闩可能是一个代价很高的操作。如果闩不是立即可用的,我们就得等待(大多数情况下都是如此),在一台多CPU机器上,我们的会话就会自旋(spin),也就是说,在循环中反复地尝试来得到闩。出现自旋的原因是,上下文切换(context switching)的开销很大(上下文切换是指被“踢出”CPU,然后又必须调度回CPU)。所以,如果进程不能立即得到闩,我们就会一直呆在CPU上,并立即再次尝试,而不是先睡眠,放弃CPU,等到必须调度回CPU时才再次尝试。之所以呆在CPU上,是因为我们指望闩的持有者正在另一个CPU上忙于处理,而且会很快放弃闩。如果出现自旋并不断地尝试想得到闩,但是之后还是得不到闩,此时我们的进程才会睡眠,或者让开CPU,而让其他工作进行。
本文来源 我爱IT技术网 http://www.52ij.com/jishu/5205.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
