oracle中lock和latch的用途
本文向各位闡述Oracle的Latch機(jī)制,Latch,用金山詞霸翻譯是門插栓,閉鎖,專業(yè)術(shù)語(yǔ)叫鎖存器,我開始接觸時(shí)就不大明白為什么不寫Lock,不都是鎖嗎?只是翻譯不同而以?研究過(guò)后才知道兩者有很大的區(qū)別。
Oracle中鎖的信息是數(shù)據(jù)塊的一部分,是物理的,并不是邏輯上屬于某個(gè)表或者某個(gè)行。Latch是Oracle提供的輕量級(jí)鎖資源,他用于快速,短時(shí)間的鎖定資源,防止多個(gè)并發(fā)進(jìn)程同時(shí)修改訪問(wèn)某個(gè)共享資源,他只工作在內(nèi)存中, 我們可以不大準(zhǔn)確的說(shuō),內(nèi)存中資源的鎖叫l(wèi)atch,數(shù)據(jù)庫(kù)對(duì)象(表,索引等)的鎖叫Lock。比如數(shù)據(jù)緩存中的某個(gè)塊要被讀取,我們會(huì)獲得這個(gè)塊的 latch,這個(gè)過(guò)程叫做pin,另外一個(gè)進(jìn)程恰好要修改這個(gè)塊,他也要pin這個(gè)塊,此時(shí)他必須等待,當(dāng)前一個(gè)進(jìn)程釋放latch后才能pin住,然后 修改,如果多個(gè)進(jìn)程同時(shí)請(qǐng)求的話,他們之間將出現(xiàn)競(jìng)爭(zhēng),沒(méi)有一個(gè)入隊(duì)機(jī)制,一旦前面進(jìn)程釋放所定,后面的進(jìn)程就蜂擁而上,沒(méi)有先來(lái)后到的概念,這個(gè)和 Lock是有本質(zhì)區(qū)別的,這一切都發(fā)生的非常快,因?yàn)長(zhǎng)atch的特點(diǎn)是快而短暫,當(dāng)然這個(gè)只是大致過(guò)程,細(xì)節(jié)部分在后面討論
先來(lái)看下Latch和Lock的區(qū)別,
1. Latch是對(duì)內(nèi)存數(shù)據(jù)結(jié)構(gòu)提供互斥訪問(wèn)的一種機(jī)制,而Lock是以不同的模式來(lái)套取共享資源對(duì)象,各個(gè)模式間存在著兼容或排斥,從這點(diǎn)看出,Latch 的訪問(wèn),包括查詢也是互斥的,任何時(shí)候,只能有一個(gè)進(jìn)程能pin住內(nèi)存的某一塊,幸好這個(gè)過(guò)程是相當(dāng)?shù)亩虝?#xff0c;否則系統(tǒng)性能將沒(méi)的保障,現(xiàn)在從9I開始,允 許多個(gè)進(jìn)程同時(shí)查詢相同的內(nèi)存塊,但性能并沒(méi)有想象中的好。
2. Latch只作用于內(nèi)存中,他只能被當(dāng)前實(shí)例訪問(wèn),而L ock作用于數(shù)據(jù)庫(kù)對(duì)象,在RAC體系中實(shí)例間允許Lock檢測(cè)與訪問(wèn)
3. Latch是瞬間的占用,釋放,Lock的釋放需要等到事務(wù)正確的結(jié)束,他占用的時(shí)間長(zhǎng)短由事務(wù)大小決定
4. Latch是非入隊(duì)的,而Lock是入隊(duì)的
5. Latch不存在死鎖,而Lock中存在(死鎖在Oracle中是非常少見的)
看看下面這個(gè)例子,你會(huì)感覺(jué)到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 |
這個(gè)進(jìn)程不斷的訪問(wèn)表上的同一個(gè)數(shù)據(jù)塊,他先會(huì)物理讀取數(shù)據(jù)塊到數(shù)據(jù)緩沖區(qū),然后在內(nèi)存中不斷的獲取這個(gè)塊的latch,現(xiàn)在只有單個(gè)進(jìn)程,運(yùn) 行的還好,10萬(wàn)次用了3秒多,但當(dāng)我拉出4個(gè)窗口同時(shí)并發(fā)的運(yùn)行這個(gè)語(yǔ)句時(shí),問(wèn)題就出現(xiàn)了,多個(gè)進(jìn)程PIN同一個(gè)數(shù)據(jù)塊,每個(gè)大概花了15秒,并且看到 他們一個(gè)一個(gè)的結(jié)束,到最后只剩一個(gè)時(shí)一閃就過(guò)去了,因?yàn)闆](méi)人和他搶了,這個(gè)實(shí)驗(yàn)展現(xiàn)了Latch競(jìng)爭(zhēng)的現(xiàn)象,對(duì)于9I提出的查詢可以共享Latch在此 我表示了質(zhì)疑。
? ? ??產(chǎn)生Latch的原因主要是:
? ? ? 1、太多的會(huì)話訪問(wèn)相同的數(shù)據(jù)塊導(dǎo)致熱塊的產(chǎn)生
? ? ? 2、共享池有太多的sql語(yǔ)句需要軟解析,沒(méi)有使用綁定變量
現(xiàn)在來(lái)看看進(jìn)程獲取Latch的詳細(xì)過(guò)程,任何時(shí)候,只有一個(gè)進(jìn)程可以訪問(wèn)內(nèi)存中的某一個(gè)塊(9I提出的Latch共享我不想考慮),如果進(jìn)程 因?yàn)閯e的進(jìn)程正占用塊而無(wú)法獲得Latch時(shí),他會(huì)對(duì)CPU進(jìn)行一次spin(旋轉(zhuǎn)),時(shí)間非常的短暫,spin過(guò)后繼續(xù)獲取,不成功仍然spin,直到 spin次數(shù)到達(dá)閥值限制(這個(gè)由隱含參數(shù)_spin_count指定),此時(shí)進(jìn)程會(huì)停止spin,進(jìn)行短期的休眠,休眠過(guò)后會(huì)繼續(xù)剛才的動(dòng)作,直到獲取 塊上的Latch為止。進(jìn)程休眠的時(shí)間也是存在算法的,他會(huì)隨著spin次數(shù)而遞增,以厘秒為單位,如1,1,2,2,4,4,8,8,。。。休眠的閥值 限制由隱含參數(shù)_max_exponential_sleep控制,默認(rèn)是2秒,如果當(dāng)前進(jìn)程已經(jīng)占用了別的Latch,則他的休眠時(shí)間不會(huì)太長(zhǎng)(過(guò)長(zhǎng)會(huì) 引起別的進(jìn)程的Latch等待),此時(shí)的休眠最大時(shí)間有隱含參數(shù)_max_sleep_holding_latch決定,默認(rèn)是4厘秒。這種時(shí)間限制的休 眠又稱為短期等待,另外一種情況是長(zhǎng)期等待鎖存器(Latch Wait Posting),此時(shí)等待進(jìn)程請(qǐng)求Latch不成功,進(jìn)入休眠,他會(huì)向鎖存器等待鏈表(Latch Wait List)壓入一條信號(hào),表示獲取Latch的請(qǐng)求,當(dāng)占用進(jìn)程釋放Latch時(shí)會(huì)檢查L(zhǎng)atch Wait List,向請(qǐng)求的進(jìn)程傳遞一個(gè)信號(hào),激活休眠的進(jìn)程。Latch Wait List是在SGA區(qū)維護(hù)的一個(gè)進(jìn)程列表,他也需要Latch來(lái)保證其正常運(yùn)行,默認(rèn)情況下share pool latch和library cache latch是采用這個(gè)機(jī)制,如果將隱含參數(shù)_latch_wait_posting設(shè)置為2,則所有Latch都采用這種等待方式,使用這種方式能夠比較 精確的喚醒某個(gè)等待的進(jìn)程,但維護(hù)Latch Wait List需要系統(tǒng)資源,并且對(duì)Latch Wait List上Latch的競(jìng)爭(zhēng)也可能出現(xiàn)瓶頸。
如果一個(gè)進(jìn)程請(qǐng)求,旋轉(zhuǎn),休眠Latch用了很長(zhǎng)時(shí)間,他會(huì)通知PMON進(jìn)程,查看Latch的占用進(jìn)程是否已經(jīng)意外終止或死亡,如果是則PMON會(huì)清除釋放占用的Latch資源。
現(xiàn)在大家可以明白,對(duì)Latch獲取的流程了,請(qǐng)求-SPIN-休眠-請(qǐng)求-SPIN-休眠。。。占用,這里有人會(huì)問(wèn)為什么要SPIN,為什么 不直接休眠等待?這里要明白休眠意味著什么,他意味著暫時(shí)的放棄CPU,進(jìn)行上下文切換(context switch),這樣CPU要保存當(dāng)前進(jìn)程運(yùn)行時(shí)的一些狀態(tài)信息,比如堆棧,信號(hào)量等數(shù)據(jù)結(jié)構(gòu),然后引入后續(xù)進(jìn)程的狀態(tài)信息,處理完后再切換回原來(lái)的進(jìn)程 狀態(tài),這個(gè)過(guò)程如果頻繁的發(fā)生在一個(gè)高事務(wù),高并發(fā)進(jìn)程的處理系統(tǒng)里面,將是個(gè)很昂貴的資源消耗,所以他選擇了spin,讓進(jìn)程繼續(xù)占有CPU,運(yùn)行一些 空指令,之后繼續(xù)請(qǐng)求,繼續(xù)spin,直到達(dá)到_spin_count值,這時(shí)會(huì)放棄CPU,進(jìn)行短暫的休眠,再繼續(xù)剛才的動(dòng)作,Oracle軟件就是這 么設(shè)計(jì)的,世界大師們的杰作,自然有他的道理,我就不在這上面再費(fèi)文字了。
系統(tǒng)發(fā)生關(guān)于Latch的等待是沒(méi)發(fā)避免的,因?yàn)檫@是Oracle的運(yùn)作機(jī)制,當(dāng)你看到很高的Latch get時(shí)并不意味著你的系統(tǒng)需要調(diào)整,有時(shí)候很高的get值背后只有很短的等待時(shí)間,我們調(diào)整的對(duì)象應(yīng)該以消耗的時(shí)間來(lái)圈定,而不是看到一個(gè)很高的獲取次 數(shù)值,當(dāng)然,獲取值異常的高出別的等待時(shí)間幾十萬(wàn)倍時(shí)我們還是要關(guān)心的,Oracle關(guān)于Latch的等待非常繁多,主要的包括share pool,library cache,cache buffer chains,buffer busy wait,每一個(gè)的調(diào)整幾乎都可以寫幾頁(yè)紙,以后慢慢完成吧。
本文轉(zhuǎn)自:http://lzfhope.blog.163.com/blog/static/6363992200951041532317/
轉(zhuǎn)載于:https://www.cnblogs.com/nizuimeiabc1/p/4802624.html
總結(jié)
以上是生活随笔為你收集整理的oracle中lock和latch的用途的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: sql从某不连续的数字中将其分段并找出缺
- 下一篇: POJ 1664 把苹果