共计 3200 个字符,预计需要花费 8 分钟才能阅读完成。
本篇内容介绍了“Latch 和 Lock 的区别是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让丸趣 TV 小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
本文向各位阐述 Oracle 的 Latch 机制,Latch,用金山词霸翻译是门插栓,闭锁,专业术语叫锁存器,我开始接触时就不大明白为什么不写 Lock,不都是锁吗? 只是翻译不同而以? 研究过后才知道两者有很大的区别。
Oracle 中锁的信息是数据块的一部分,是物理的,并不是逻辑上属于某个表或者某个行。Latch 是 Oracle 提供的轻量级锁资源,他用于快速,短时间的锁定资源,防止多个并发进程同时修改访问某个共享资源,他只工作在内存中,我们可以不大准确的说,内存中资源的锁叫 latch,数据库对象 (表,索引等) 的锁叫 Lock。比如数据缓存中的某个块要被读取,我们会获得这个块的 latch,这个过程叫做 pin,另外一个进程恰好要修改这个块,他也要 pin 这个块,此时他必须等待,当前一个进程释放 latch 后才能 pin 住,然后 修改,如果多个进程同时请求的话,他们之间将出现竞争,没有一个入队机制,一旦前面进程释放所定,后面的进程就蜂拥而上,没有先来后到的概念,这个和 Lock 是有本质区别的,这一切都发生的非常快,因为 Latch 的特点是快而短暂,当然这个只是大致过程,细节部分在后面讨论
先来看下 Latch 和 Lock 的区别,
1. Latch 是对内存数据结构提供互斥访问的一种机制,而 Lock 是以不同的模式来套取共享资源对象,各个模式间存在着兼容或排斥,从这点看出,Latch 的访问,包括查询也是互斥的,任何时候,只能有一个进程能 pin 住内存的某一块,幸好这个过程是相当的短暂,否则系统性能将没的保障,现在从 9I 开始,允 许多个进程同时查询相同的内存块,但性能并没有想象中的好。
2. Latch 只作用于内存中,他只能被当前实例访问,而 L ock 作用于数据库对象,在 RAC 体系中实例间允许 Lock 检测与访问
3. Latch 是瞬间的占用,释放,Lock 的释放需要等到事务正确的结束,他占用的时间长短由事务大小决定
4. Latch 是非入队的,而 Lock 是入队的
5. Latch 不存在死锁,而 Lock 中存在(死锁在 Oracle 中是非常少见的)
看看下面这个例子,你会感觉到 Latch 的存在
SQL CREATE TABLE MYTEST AS SELECT OBJECT_NAME FROM USER_OBJECTS WHERE ROWNUM = 4;
Table created
SQL SET TIMING ON
SQL
DECLARE lv_name VARCHAR2(25) :=
BEGIN
FOR i IN 1..100000 LOOP
SELECT OBJECT_NAME INTO lv_name FROM MYTEST WHERE ROWNUM = 1;
END LOOP;
END;
/
PL/SQL procedure successfully completed
Executed in 3.359 seconds
这个进程不断的访问表上的同一个数据块,他先会物理读取数据块到数据缓冲区,然后在内存中不断的获取这个块的 latch,现在只有单个进程,运 行的还好,10 万次用了 3 秒多,但当我拉出 4 个窗口同时并发的运行这个语句时,问题就出现了,多个进程 PIN 同一个数据块,每个大概花了 15 秒,并且看到 他们一个一个的结束,到最后只剩一个时一闪就过去了,因为没人和他抢了,这个实验展现了 Latch 竞争的现象,对于 9I 提出的查询可以共享 Latch 在此 我表示了质疑。
产生 Latch 的原因主要是:
1、太多的会话访问相同的数据块导致热块的产生
2、共享池有太多的 sql 语句需要软解析,没有使用绑定变量
现在来看看进程获取 Latch 的详细过程,任何时候,只有一个进程可以访问内存中的某一个块 (9I 提出的 Latch 共享我不想考虑),如果进程 因为别的进程正占用块而无法获得 Latch 时,他会对 CPU 进行一次 spin(旋转),时间非常的短暂,spin 过后继续获取,不成功仍然 spin,直到 spin 次数到达阀值限制(这个由隐含参数_spin_count 指定),此时进程会停止 spin, 进行短期的休眠,休眠过后会继续刚才的动作,直到获取 块上的 Latch 为止。进程休眠的时间也是存在算法的,他会随着 spin 次数而递增,以厘秒为单位,如 1,1,2,2,4,4,8,8,。。。休眠的阀值 限制由隐含参数_max_exponential_sleep 控制,默认是 2 秒,如果当前进程已经占用了别的 Latch,则他的休眠时间不会太长(过长会 引起别的进程的 Latch 等待),此时的休眠最大时间有隐含参数_max_sleep_holding_latch 决定,默认是 4 厘秒。这种时间限制的休 眠又称为短期等待,另外一种情况是长期等待锁存器(Latch Wait Posting),此时等待进程请求 Latch 不成功,进入休眠,他会向锁存器等待链表(Latch Wait List) 压入一条信号,表示获取 Latch 的请求,当占用进程释放 Latch 时会检查 Latch Wait List,向请求的进程传递一个信号,激活休眠的进程。Latch Wait List 是在 SGA 区维护的一个进程列表,他也需要 Latch 来保证其正常运行,默认情况下 share pool latch 和 library cache latch 是采用这个机制,如果将隐含参数_latch_wait_posting 设置为 2,则所有 Latch 都采用这种等待方式,使用这种方式能够比较 精确的唤醒某个等待的进程,但维护 Latch Wait List 需要系统资源,并且对 Latch Wait List 上 Latch 的竞争也可能出现瓶颈。
如果一个进程请求,旋转,休眠 Latch 用了很长时间,他会通知 PMON 进程,查看 Latch 的占用进程是否已经意外终止或死亡,如果是则 PMON 会清除释放占用的 Latch 资源。
现在大家可以明白,对 Latch 获取的流程了,请求 -SPIN- 休眠 - 请求 -SPIN- 休眠。。。占用,这里有人会问为什么要 SPIN,为什么 不直接休眠等待? 这里要明白休眠意味着什么,他意味着暂时的放弃 CPU,进行上下文切换(context switch),这样 CPU 要保存当前进程运行时的一些状态信息,比如堆栈,信号量等数据结构,然后引入后续进程的状态信息,处理完后再切换回原来的进程 状态,这个过程如果频繁的发生在一个高事务,高并发进程的处理系统里面,将是个很昂贵的资源消耗,所以他选择了 spin,让进程继续占有 CPU,运行一些 空指令,之后继续请求,继续 spin,直到达到_spin_count 值,这时会放弃 CPU,进行短暂的休眠,再继续刚才的动作,Oracle 软件就是这 么设计的,世界大师们的杰作,自然有他的道理,我就不在这上面再费文字了。
系统发生关于 Latch 的等待是没发避免的,因为这是 Oracle 的运作机制,当你看到很高的 Latch get 时并不意味着你的系统需要调整,有时候很高的 get 值背后只有很短的等待时间,我们调整的对象应该以消耗的时间来圈定,而不是看到一个很高的获取次 数值,当然,获取值异常的高出别的等待时间几十万倍时我们还是要关心的,Oracle 关于 Latch 的等待非常繁多,主要的包括 share pool,library cache,cache buffer chains,buffer busy wait,每一个的调整几乎都可以写几页纸,以后慢慢完成吧。
“Latch 和 Lock 的区别是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注丸趣 TV 网站,丸趣 TV 小编将为大家输出更多高质量的实用文章!