学习latch笔记

作者:xiayulai | 分类: 大话技术 | 标签: | 日期:2008-08-31

<!– @page { size: 21cm 29.7cm; margin: 2cm } P { margin-bottom: 0.21cm } –>

个人认为科学技术之间存在一定的相关性的,先举一个例子,来比较浅显的了解一下latch的一些特点。下图为一张十字路口照片,来来往往的车辆就是靠十字路口的一个交通信号灯来指挥的,当然有时候也会有按照交通警察的指令来执行。

<!– @page { size: 21cm 29.7cm; margin: 2cm } P { margin-bottom: 0.21cm } –>

中国的交通,十字路口有交通信号灯,信号灯周期性的变化。当东西直行的信号灯是绿的时,东西方向的汽车可以行走,此时南北方向的车需要等待;当南北方向的信号灯是绿的时候,南北方向的车是可以行走的,东西方向的车要等待。当一个方向为绿灯时另一个方向一定是红灯,除非线路故障。看到这个图,我突然想到和latch很有一比,到底有多少呢,让我们一起看看下面几个问题:

1、那么信号灯是起一个什么作用呢?

告诉行使的车里和行人你能不能通过十字路口。

2、汽车等待的是什么?

汽车在等待交通信号灯变成绿色,这样可以通过。

3、汽车是使用信号灯呢还是使用十字路口的那一块马路呢?

汽车得到绿色信号灯之后,会立即行使通过路口,他使用的就是那一个马路。

4、 同时得到这个绿色信号灯的是不是不仅仅一辆车?

同时看到绿灯的车辆有很多,并发的比较多。

5、信号灯变化时间越长是不是就堵的更严重?

信号灯的时间越长,导致一次等待的时间过长,押车的长度会变长,通过路口的速度要明显小于正常形式的速度,这样导致车会越来越多的堵在路上。

6、是不是有的车得不到中间的道路资源他就不等待信号灯而直接右柺呢?

有些车辆在直行的时候没有得到绿灯,他们还有别的方向可以选择,就会右转来直接走掉

7、是不是车辆的个头越大,同时通过路口的车辆就越少?

一次占用整个车道,那岂不是要让后边的车没法通过?

8、当一辆车在一次信号灯没有通过路口时,是不是继续等待,下一次绿色信号灯亮的时候是不是他第一时间可以通过?

当一次绿灯正好没有通过路口,下一次绿灯到来的时候他就可以比较迅速的得到绿灯信号,而快速通过。

发现交通信号灯这个设计很有意思,和oraclelatch很像,不知道是谁学习的谁.

  • Latch到底是什么呢?

是能不能独自访问或执行某一种共享资源的信号灯。从程序上来讲就是一个变量,标记了某个资源的一个状态。

Latch有三种类型,父latch,子latch,独立latch。其中,在v$latch_parent这个表中存放的是独立latch和父latch,每一个latch存放一条记录。子latch放在 v$latch_children表中,每个子latch存放一条记录,只有少数的latch有子latch,所以在v$latch_children表中,其latch name是一样的,但是其地址不一样,表明他保护block不想同。在v$latch表中,保存了所有的latch的聚合信息,在这里能看到宏观的latch信息,在v$latch_children中可以看到微观的每个latch的信息。

根据概念理解,对于共享的数据结构都是需要使用latch进行保护的,有些数据结构使用一个latch有些数据结构使用多个latch(子latch),多个latch的使用可以增加并发度,因为不用访问一个资源而占用了整个链表的latchlatch的访问是独享的

<!– @page { size: 21cm 29.7cm; margin: 2cm } P { margin-bottom: 0.21cm } –>

看了latch的概念,那么进程如何得到latch呢?

进程得到latch的方式:willing-to-waitno_wait两种方式:

Willing-to-wait方式是请求一个latch如果一次请求没有获得,然后又有经过spintry again经过多次的spin_SPIN_COUNT如果还没有得到latch则进入到sleep状态,进入sleep前,它需要先安排一下他的后事,不能一睡不起呀(如何醒来,超时和repost,还有就是通知v$session_wait自己发生了latch free wait,从这里可以知道,每次sleep都会对应着一个latch free wait eventspin也可以称之为active waitcpu时间片该进程还没有消耗完毕,那么这样进程还是在消耗cpu时间的。这样的方式请求的latch的(level)级别要比自己持有的高才可以,为什么呢?如果a进程占有一个level 5latch,它去请求一个level3latch,而进程b,占有这个level3latch,又去请求那个level 5latch,这样会有什么问题呢?因为它是可以去spin的,又是可以去sleep的,sleep之后还是继续重复?那就永远没有完没有了了。所以呢,levelrequest是有level顺序的,不能随便的请求。

为什么要spin呢?spin是对于多cpu系统而言的,一个cpu是没有必要的,因为,spin是一个进程在cpu时间片内等待一个latch,它会让spin进程去其他的cpupin一下,如果有其他的进程释放了该latch,那么就可以得到了,又因为一个cpu,在一个时刻只能处理一个进程,进程切换的代价又很高,要建立上下文环境,所以尽量在cpu没有切换的时候能得到latch最好。Spin的次数也是有一个参数来指定的,_SPIN_COUNT,文档上有一个公式说

_SPIN_COUNT * sleeps / misses 的值越小越好,但是我没有明白过来,请大牛们解释一下。

v$latch中,有getsmisses。那么gets是什么意思呢?gets是进程通过willng-to-wait得到的latch的次数,misseswilling-to-wait模式并且没有pin也没有得到latch的次数。那么经过多次的spin得到latch计作一个gets,经过多次spin没有的到latch,那就是sleep了。

Sleepwilling-to-wait模式请求latch失败了,然后就要去sleepsleep要去告诉v$session_waitV$SYSTEM_EVENT发生了latch free 等待事件。Sleep之后还是要醒来的,要么是闹钟(超时),要么就是告诉别人叫他一下(repost)。Sleep醒来之后,其下次的sleep时间要变长的,不知道为什么,睡得越多,每次睡眠的时间就越长(2s),但是当一个进程持有latch的时候睡眠的时间会很短(4厘秒)。1=1000毫秒(ms)1毫秒=11,000(s) 1=1,000,000 微秒(μs) 1微秒=11,000,000(s) 1=1,000,000,000 纳秒(ns) 1纳秒=11,000,000,000(s) 1=1,000,000,000,000 皮秒(ps) 1皮秒=11,000,000,000,000(s)

在上面看来,latch如果出现sleeps比较多,造成的影响是比较严重,因为每次request latch都会耗用cpu时间,sleep说明了白白浪费了cpu时间,这样会造成资源的浪费。

No_wait方式去请求一个latch,有两种情况:1、他请求的latch有多个类型相同的latch可以请求,会先请求一个,如果得不到,就请求下一个同样的latch,如果都扫描了一遍,还是没有得到,则转入willing-to-wait2、请求的latch级别与请求的相同或者低的时候,因为他有deadlock保护,所以可以。

No_wait方式在v$latch的记录为:IMMEDIATE_GETS IMMEDIATE_MISSES

Latchcleanup,在latch的使用过程中,可能会出现一些异常,而导致有些latch被异常占有得不到释放,这样就会有问题了,别的进程过来请求不到。出现这样的异常pmon进程会跟进处理,对于其处理的流程来说,最重要的莫过于将没有提交的事物回滚,那么就需要latch支持恢复,那么latch在开始操作前会先写一些信息去latch的恢复区。Pmon 3秒钟会自动运行一下,但是这也使很长的一段时间了,所以在进程在请求一个latch失败多次之后,会post pmon进程去check一下占有这个latchprocess是不是正常。

Spingetsmissessleepcleanup

Spin是对于多cpu系统而设计的,目的是为了能够尽量不发生进程交换的情况下得到latch,该进程去查看别的cpu有没有释放其需要的latch如果能得到就可以在一次cpu时间内处理完事情,多好呀。

Gets willing-to-wait模式的not spinspin(不论一次还是多次spin)的gets

Misses willing-to-wait fail to get without spin

Sleep 在一次cpu时间内没有得到latch,就会睡眠

IMMEDIATE_GETSno_wait模式的get

IMMEDIATE_MISSESno_wait模式的miss

Cleanup 占有latch的进程出现异常,需要PMON进行清理,以免长期占有latch。在进程得到latch之后需要先将恢复数据写到恢复区,保证出现异常之后能够正常恢复。

  • 查看latch的视图:

1select latch#, name from v$latchname

可以看到latch的名字

2、Select total_waits from v$system_event where event=‘latch free’;

2、Select sum(sleeps) from v$latch;

上面这两个的结果实一样的。

3、select name, gets, misses, immediate_gets, immediate_misses, sleeps from v$latch order by sleeps;

4select * from (SELECT file#, dbablk, class, state, TCH FROM X$BH b,v$latch_children lc WHERE b.HLADDR=lc.addr order by TCH desc) where rownum<=10;

sql可以查询一下hot block,其中 TCH touch count header? 该值大,说明了被访问的次数相当多。X$bh中的HLaddr就是说的在block头的latch地址,正好是v$latch_childrenaddr

6人发表了评论  ↓发表评论↓
  • 看到latch就想起当时怎么没好好听操作系统原理,哎

    棉花糖ONE @ September 1, 2008 |

  • 小强的处女作啊。。。。。

    vogts @ September 1, 2008 |

  • 分析的通俗易懂,非常精彩。理解也很深刻

    sky @ September 11, 2008 |

  • 看到latch就想起当时怎么没好好听操作系统原理,哎

    最好深入了解一下Os的 spin lock机制..

    jametong @ September 12, 2008 |

  • SPIN COST= Spin_count * sum(sleeps) / sum(misses)这个公式计算的是SPIN的cost。由于一次的sleep前一定有了一个spin 所以 spin_count*sleeps 计算的是 空操作的次数。然后在除 misses。大致的意思是:每个miss 需要的空操作的数目。越小越好。

    xiaodao @ February 24, 2009 |

  • Spin_count * sum(sleeps) / sum(misses)
    这个公式,分解一下看,其实不难。Spin_count是个常量,先把它去掉。假设有一个闩,经历了4次睡眠才得到,sleeps / misses 结果是几,4。再假设它经历了8次睡眠才得到,哪结果就是8了。这个结果当然是越小越好了。sleeps / misses 其实是睡了几次才得到闩。用这个值乘以每次睡眠Spin的次数,就是SPIN 的总 COST了。

    呵呵 @ May 17, 2009 |

表情:<( ̄︶ ̄)> | (⊙ˍ⊙) | >﹏< | b( ̄▽ ̄)d | (─.─||) | (^_-)

[ Ctrl+Enter提交 ]

DBA