查看: 67515|回复: 158

[精华] latch入门?(最新更新part4:这才是真正的latch)---你所不知道的latch

[复制链接]
论坛徽章:
6
ITPUB季度 技术新星
日期:2011-08-31 15:27:58ITPUB十周年纪念徽章
日期:2011-11-01 16:26:292012新春纪念徽章
日期:2012-01-04 11:57:36咸鸭蛋
日期:2012-03-05 13:10:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:16:00优秀写手
日期:2013-12-18 09:29:09
跳转到指定楼层
1#
发表于 2011-4-29 13:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
(入门1)
一直想点文章关于Latch的,又一直没写,一是因为懒,二是一直觉得现在关于Latch的书那么多,还有必要写吗?
后来,看到了一些帖子:
1.一个帖子,帖主发现了大量cache buffer chain,检查过了都是select造成了,遂对oracle声称的shared latch产生质疑。
2.某帖,做了buffer busy wait和cache buffer chain的实验,得出很多结论。可从头到尾,帖子的实验中,buffer busy wait和cache buffer chain都是同时出现的。如果真的那么清楚这两者的区别,能够模拟出一种大量buffer busy wait却没有任何cache buffer chain的实验吗?


如果你也有这些问题,你可能也跟我曾经一样,似懂非懂。所以,终下决心写点东西,以做分享,希望对菜鸟们有些帮助(高手请一笑而过):
请往下看,注意,再次声明,本文不是介绍各种各样latch的高级教程。本文只讲基础,那就是,你知道太多种latch了,可是,你真的知道什么是latch吗?

这点,就要从我们为什么需要latch上来说了,latch到底在保护什么?如果没有latch,什么样的操作会损坏latch想要保护的结构?

(数据结构第一章:链表。)

答:latch保护的是链表。会损坏链表的,不是对于链表上的数据的读写操作---这些操作是完全可以并行的。
会损害链表结构的,是将链表上的块摘下,或者插入新的块的操作----这样的操作,如果不存在并发控制,是会损坏链表的。

譬如,一个链表,a--b--c--e--
如过现在想往b与c间,插入新节点m。那么我就需要更改b的next node的指针,以及c的previous node指针。

如果没有latch做并发控制,那么与此同时,如果另一个进程也向b与c(往a与b,c与e之间不会有问题)之间插入n,也需要去更改b和c的指针,那就有可能造成这条链被破坏,譬如结构变成:
a--b--n
m--d--e
这就是latch的意义,用于挂链,下链!

而对于我们的cbc latch,锁控制的就是从disk上将block读入内存中的链上,以及将链上的block摘下并写回disk。
所以,latch只关心你操作的目标block是否在链上---因为可能牵扯到上链下链,而不关心你这个操作本身是select还是insert还是delete还是update!cbc latch与操作是select还是DML没有一毛关系!

所以,现在再回去看第一个问题----为什么select还是会产生大量的buffer cache chain争用?
现在你看清了,貌似这个问题问的有根有据,其实,问的原因和结果是没有联系的两码事。

那么shared latch是否真的存在吗?cache buffer chain是可share的吗?答案是:YES。并且完全可以通过实验模拟出来清楚的看到他的作用。

----------------------------------------------------------------------------------
(入门2)
先以一个问题引入:
10g中v$latch的底层表X$KSLLD为例,他的全称是
X$KSLLD: [K]ernel [S]ervice [L]? Management [L]atch [D]escriptor
请问,问号这里的L,是什么含义?猜测下,再往下看。



引入些补充知识:
对于操作系统来说,可以划分为三种lock,我们称之为OS Lock:
1.spinlock。最轻量级的lock,当获取不到时,发生自旋,不用发生上下文切换。
2.mutex--互斥量。当获取不到时,将发生上下文切换。好处是,不会使CPU发生空转。但是如果频繁的切换严重消耗资源。
3.semaphores--信号量。与mutex(互斥量类似),当获取不到时,发生上下文转换。但是与mutex的区别是,mutex互斥量,同一时间只能被一个进程获取,而信号量,可以同时好几个进程获取。


从上面我们可以看出,spinlock是最轻量级的而,oracle的latch是封装在系统的spinlock之上。
而oracle也有mutex,11g中,oracle引入了更轻量级的mutex,以取代某些latch。你对此就没有置疑过吗?spin才是最轻量的啊,不用发生上下文转换,mutex要上下文转换的,怎么可能比spin轻量?

MUTEX当然不可能比SPIN更轻量!oracle那么说因为,oracle引入的mutex不是上面所说的OS mutex!而是同样构建于spin之上KGX mutex。


扯远了,我们继续latch:
下面我们再来看X$KSLLD,
X$KSLLD: [K]ernel [S]ervice [L]? Management [L]atch [D]escriptor
问号处的[L],现在你知道了,这里是Lock,但是如果没有上面的知识,你很难理解这里为什么会是Lock。你会觉得,Lock怎么又在这里跟latch扯上关系?
事实上,我也看到某些大师将其翻译成:
X$KSLLD: [K]ernel [S]ervice [L]Latch Management [L]atch [D]escriptor
因为没有以上的知识,无法理解这里为什么又扯上了Lock。但是,有了上文的描述,你知道,这里L就是lock,只不过这个lock的意思不是
oracle里面各种各样的TX,TM等锁,而是OS Lock,用来控制进程间的交互与并行。



继续下去:latch是如何实现的,真的只是内存中的一个标志位那么简单吗?
很多人是这么理解latch的,一个标志位:A。可以有两种选择:
A=0 或者 A=1。任何进程想要对共享的资源进行操作时,先去看A,如果是0,则代表未被使用,那么置位成1,然后自己去使用,
如果是1,则等待。


就这么简单?

对的,你表面上看到的latch就这么简单,可是背后的故事,你知道吗?

现在想想:为什么我们要对共享资源加标志位?因为我们想以此控制对资源的串行访问。但是请别忘了,你这个标志位本身,也是一种资源,对这种标志位本身的访问,也是会发生冲突的!

再往微观处想想:现在标志A为0,而有两个进程P1与P2,在并行运行着,这时,同时要用到A。于是P1先将A从内存读入,检测A是0,于是准备将A置为1,在P1将A写回内存前,P2也将A读入,此时A仍然是0。好了,P2也发出命令将A置1。于是,P1,P2都认为是自己成功将A置为1的,拥有对资源的操作权。
然后呢?链表被破坏了。




----------------------------------------------------------------------------------
谢谢大家的捧场,懒人为了兄弟们咬牙再写点
(入门3)
这一节先回答第一节和第二节的几个疑问:
1.如果真的这么明白两者的区别,能模拟出一个大量buffer busy waits竞争却没有任何cbc latch争用的实验吗?

相信经过前面的描述,对latch到底是在做什么应该有了一点了解了。
正如第一讲中所阐述的,与select/DML相关的是buffer busy waits,而cache buffer chains与select/DML无关。
那么cache buffer chains与什么有关?
答:索引。准确的说,是唯一索引。

当一个操作,走的是唯一索引的话,那么oracle默认目标block是存在于目标链上的,这时,oracle会以shared的模式去获取
cbc latch。如果之后oracle发现弄错了,这个目标块不存在于链上。那么这时,oracle再会尝试以exclsive模式去获得
cbc latch,以将block挂往链上。
但是,如果是全表扫描,oracle会默认的认为目标block肯定是不存在于目标链上的,oracle会直接以exclsive模式去获得cbc latch。


这个实验是老早以前证明cbc是shared latch做的。实验我懒得再去做一遍了,相信大家看完后大家都能做出来,我就直接把实验结果写出来了。
当然,有兴趣的朋友可以做下把过程贴出来 ,我就偷懒下了,呵呵。


传统的buffer busy waits实验,这么做,我们就可以完全搞清楚cache buffer chains与buffer busy waits。
两个session,对于同一数据块的操作。

a.表上无索引,DML操作。
实验结果:大量cbc latch争用,大量buffer busy waits竞争。

b.表上无索引,SELECT操作。
实验结果:大量cbc latch争用, 无任何buffer busy waits竞争。

c.表上有唯一索引,DML操作。
实验结果:无任何cbc latch争用,大量buffer busy waits竞争。

d.表上有唯一索引,SELECT操作。
实验结果:无任何cbc latch争用,无任何buffer busy waits竞争。


现在,shared latch是否存在,cbc latch到底起什么作用,与buffer busy waits的区别,还要我多说什么吗?



2.第二节留下的问题:操作系统如何来做到操作FLAG A时防止并行带来的冲突?
答:操作系统第二章:原子性操作
当oracle调用spin函数的时候,操作系统把“一个cpu的读取flag进入内存,检查flag值,值位,写回内存”封装成一个
原子性操作。以保证这个操作不会被中断。flag A不会同时被其他CPU修改。
那么操作系统是如何做到这一点的呢?
答:通过锁BUS LINE(总线)。
CPU到内存的结构是这样的:cpu core+cache+Bus Line.
其中,Bus Line是公用的。你的CPU可以是N核,但是,BUS Line是所有CPU共享的。所有CPU与内存的交互都是
通过这个BUS LINE。所以,当一个CPU发出spin命令时候,会锁住总线,以阻止其它CPU对内存的访问与操作。以此来保证对于标志位
的至位是原子性的。
其实这里面门道还是很多的,还有spin本身也分成很多类型,oracle用的是其中比较原始的一种。不过这些就太贴近操作系统,离oracle太远了。
所以这里就不赘述了。有兴趣的朋友们可以自己去查。


----------------------------------------------------------------------------------------------------
(入门4)
与前三节基本都是自己的研究不同,从这一节开始,很多东西都是外国佬的成果,不过我也做过实验可以基本保证正确。
下面开始:latch是如何运作的。
在9i以前,oracle内部使用自旋--睡眠--自旋--睡眠模式来不断尝试对latch的获取,每次的睡眠时间依次是:
0.01-0.01-0.03-0.03-0.08-0.07-0.16-0.23-0.4-0.39-0.73-0.72-1.39-1.38-2.04-2.04.....

但是,从9i开始,这种情况已经变了,latch不再使用这种模式,不再是很多人印象中那种毫无纪律一窝蜂的抢夺,latch使用一种队列机制。
这个队列的四个特性:
1.FIFO先进先出
2.可插队
3.队列中的latch请求每次只能有一个(第一个)被外部唤醒。队列中的latch请求不会自动醒来。
4.这个队列并不是必定存在的。

当有一个latch正在被以exclusive模式获得时,
此后继续来的对此latch申请分两种情况:
1.如果申请的也是exclusive模式,那么cpu会自旋一定次数(注意,我这里没说是_spin_count次)不断尝试获取,如果
还是没能获取,那么将进入队列中等待。(如果一定次数内能获取,就不用进入队列,所以说这个队列并不是必定存在的

2.如果申请是shared latch,发现已经被exclusive持有了,那么会一次都不自旋的立刻进入队列之中睡眠。


如果现在这个latch一直不被释放,那么后面队列中的申请永远都不会自动醒来。只有,当一个hold的latch被释放时候,会发送一个唤醒信号给队列,仅唤醒队列中的第一个睡眠的等待

举个例子,比如,现在一个execute模式的latch在hold,后面接着依次来了5个进程希望获得share latch,发现latch
被以exclusive获得,那么将一次都不自旋的依次进入队列等待。现在这个队列是这样的:
1s-2s-3s-4s-5s,
那么当excluse模式的latch释放后,他会发个信号给等待队列,等待队列中的第一个latch会被唤醒并且去获得shared latch。
所以,这个队列就变成了:
2s-3s-4s-5s!
你会发现,虽然都是share模式的latch!但是并没有一次性被全部唤醒!

所以如果你经常做system的dump,你可能看到过这种情况,那就是一个进程在申请获得以shared方式获得一个latch,
你去检查那个latch,发现这个latch是在以share模式持有的!
所以有了share waiting share!这还不是最神奇的,更神奇的还在后面。


这种latch的队列,是允许插队的。也就是说,譬如现在latch正在被share持有,而等待队列是:
2s-3s-4s-5s
现在来了第6个share模式的申请,那么他并不会进入等待队列中,而是会直接获得latch,因为share与share是兼容的!


我们来说说更神奇的事。在9i的时候,这种方式还有很多bug。
不知道你有没遇到过,一个查询莫名的hang住,或者数据库hang住。如果去做个trace,你可能会发现,进程正在等待获得一个latch,而当你再去检查那个latch时居然发现,那个latch并没有被任何进程持有!是free的!也就是说,latch request waiting for a free latch!
这种bug的原因就是因为这个latch request处在上面所说的队列中,并且由于某些原因,当前面latch释放时并没有将它唤醒,而它也绝对不会自己醒来。


如果你去找Oracle开SR,Oracle会让你用这个隐藏参数解决:
_enable_reliable_latch_waits=false.
reliable--依赖。现在应该能看懂这个隐藏参数的意思了吧。




......(未完待续).......

看完觉得有点帮助的话帮忙顶下,您的支持,我的动力








[ 本帖最后由 Kevin__Zhang 于 2011-5-12 18:38 编辑 ]
论坛徽章:
6
ITPUB季度 技术新星
日期:2011-08-31 15:27:58ITPUB十周年纪念徽章
日期:2011-11-01 16:26:292012新春纪念徽章
日期:2012-01-04 11:57:36咸鸭蛋
日期:2012-03-05 13:10:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:16:00优秀写手
日期:2013-12-18 09:29:09
2#
 楼主| 发表于 2011-4-29 13:28 | 只看该作者
沙发是自己滴

使用道具 举报

回复
论坛徽章:
122
现任管理团队成员
日期:2011-05-07 01:45:08
3#
发表于 2011-4-29 13:40 | 只看该作者
顶你~

使用道具 举报

回复
论坛徽章:
58
生肖徽章2007版:马
日期:2009-11-06 23:12:33授权会员
日期:2013-01-10 14:38:592013年新春福章
日期:2013-02-25 14:51:24马自达
日期:2013-08-07 10:54:45红旗
日期:2013-08-09 13:48:48劳斯莱斯
日期:2013-09-12 15:56:37萤石
日期:2013-10-31 08:44:19优秀写手
日期:2013-12-18 09:29:13Jeep
日期:2014-01-14 10:53:432014年新春福章
日期:2014-02-18 16:43:09
4#
发表于 2011-4-29 13:43 | 只看该作者
支持原创

使用道具 举报

回复
求职 : 数据库开发
论坛徽章:
27
至尊黑钻
日期:2015-10-19 09:57:44红钻
日期:2015-10-19 09:57:06ITPUB15周年纪念
日期:2018-10-26 11:37:06
5#
发表于 2011-4-29 13:44 | 只看该作者
up

使用道具 举报

回复
论坛徽章:
1
2010新春纪念徽章
日期:2010-03-01 11:08:29
6#
发表于 2011-4-29 13:46 | 只看该作者
先顶了再说

使用道具 举报

回复
论坛徽章:
3
2010广州亚运会纪念徽章:壁球
日期:2011-02-12 15:35:472011新春纪念徽章
日期:2011-02-18 11:43:33咸鸭蛋
日期:2011-12-01 17:00:20
7#
发表于 2011-4-29 13:50 | 只看该作者
up

使用道具 举报

回复
论坛徽章:
5
生肖徽章2007版:牛
日期:2009-12-03 13:37:50ITPUB9周年纪念徽章
日期:2010-10-08 09:34:02ITPUB十周年纪念徽章
日期:2011-11-01 16:23:262012新春纪念徽章
日期:2012-01-04 11:53:292013年新春福章
日期:2013-02-25 14:51:24
8#
发表于 2011-4-29 13:51 | 只看该作者
这个不顶不行呀

使用道具 举报

回复
论坛徽章:
1
2010新春纪念徽章
日期:2010-03-01 11:08:29
9#
发表于 2011-4-29 13:52 | 只看该作者
还没切入进入就未完待续……

使用道具 举报

回复
论坛徽章:
59
狮子座
日期:2016-03-26 13:35:402013年新春福章
日期:2013-02-25 14:51:24双黄蛋
日期:2013-02-25 11:06:15ITPUB 11周年纪念徽章
日期:2012-10-09 18:06:20灰彻蛋
日期:2012-04-25 13:19:33紫蛋头
日期:2012-03-14 11:16:09最佳人气徽章
日期:2012-03-13 17:39:18玉石琵琶
日期:2012-02-21 15:04:38鲜花蛋
日期:2011-11-30 14:13:01ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15
10#
发表于 2011-4-29 14:06 | 只看该作者
什么是shared latch?有什么用?latch为什么要share?
好像就两种latch吧,一种willing to wait, 一种no wait,貌似没有willing to share的latch
latch本来就是存在那里的,让process去抢的,谁抢到了就可以对latch保护的东西做操作
share意思就是我抢到了,但是呢我什么都不做,如果有另外一个人要用,我就贡献出来给他用?
这跟我抢到这个latch,然后释放这个latch继续给别人去抢,好像没分别吧

使用道具 举报

回复

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

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表