《Oracle高并發(fā)系列1:DML引起的常見(jiàn)問(wèn)題及優(yōu)化思路》要點(diǎn):
本文介紹了Oracle高并發(fā)系列1:DML引起的常見(jiàn)問(wèn)題及優(yōu)化思路,希望對(duì)您有用。如果有疑問(wèn),可以聯(lián)系我們。
作者介紹
Oracle數(shù)據(jù)庫(kù)是設(shè)計(jì)為一個(gè)高度共享的數(shù)據(jù)庫(kù),這里所說(shuō)的“共享”,可以從數(shù)據(jù)庫(kù)共享內(nèi)存、后臺(tái)進(jìn)程、cursor、執(zhí)行計(jì)劃、latch等方面去理解.Oracle如此設(shè)計(jì)的目的是以最小的系統(tǒng)開銷、最大化地支持更多的并發(fā)會(huì)話.也是基于這個(gè)設(shè)計(jì)思想,所以O(shè)racle單個(gè)實(shí)例的垂直擴(kuò)展能力一直是DB領(lǐng)域內(nèi)的佼佼者.
之前曾經(jīng)看到PG大牛的文章分析關(guān)于Oracle的CursorPin S為什么不會(huì)在PostgreSQL里面出現(xiàn),其主要原因是PostgreSQL的執(zhí)行計(jì)劃不是全局共享的,而Oracle里面同樣的Cursor在不同session間一般情況下都是可以共享的(Oracle在某些條件下會(huì)也觸發(fā)重新硬解析).這樣的設(shè)計(jì)客觀來(lái)講其實(shí)各有優(yōu)劣,雖然PG的plan cache是不同會(huì)話不共享的,避免了高并發(fā)時(shí)不同會(huì)話對(duì)同一個(gè)cursor產(chǎn)生爭(zhēng)用,但是也意味著同樣的并發(fā)會(huì)話數(shù)的情況下,PG的會(huì)話所需求的cache會(huì)更多,而且每個(gè)會(huì)話都至少要parse一次;或者反過(guò)來(lái)說(shuō)同樣的資源限制的前提下,Oracle支持的并發(fā)數(shù)更高.
引用一位Oracle 7的OCP,資深Oracle老司機(jī)的一段話:“早期Oracle就是使用session私有內(nèi)存,但當(dāng)負(fù)載并發(fā)增加時(shí),內(nèi)存消耗成了問(wèn)題,而且執(zhí)行計(jì)劃無(wú)法共享,增加率parse時(shí)間,對(duì)于OLTP系統(tǒng)parse時(shí)間的增加對(duì)于整體執(zhí)行時(shí)間影響較大.因此Oracle基于這一點(diǎn)進(jìn)行了優(yōu)化,包括session cached cursor和shared pool等,減少了SQL執(zhí)行過(guò)程中的parsing time和planning time.但沒(méi)有免費(fèi)的午餐,肯定會(huì)有其它消耗,類似內(nèi)存結(jié)構(gòu)的并發(fā)保護(hù)上的成本.總之:
這里不探討哪個(gè)數(shù)據(jù)庫(kù)更NB,每種數(shù)據(jù)庫(kù)技術(shù)的發(fā)展會(huì)受多種因素的影響,包括商業(yè)戰(zhàn)略、市場(chǎng)需求、軟硬件技術(shù)成熟度等.我們采用Oracle多年,對(duì)于Oracle數(shù)據(jù)庫(kù)有深厚的感情,但是目前也同時(shí)義無(wú)反顧地投入開源數(shù)據(jù)庫(kù)和NoSQL的懷抱,技術(shù)無(wú)好壞,最適合應(yīng)用場(chǎng)景的就是最好的.這里只重點(diǎn)探討,當(dāng)Oracle數(shù)據(jù)庫(kù)的這些“共享”資源,遭遇高并發(fā)時(shí)的問(wèn)題發(fā)生的原因和應(yīng)對(duì)措施.
這里談的是思路,不是具體的命令.
這里的處理方法,是基于過(guò)往發(fā)生過(guò)的實(shí)際案例總結(jié)而來(lái).
Oracle的表是堆表,索引是B樹,當(dāng)對(duì)表做DML時(shí),Oracle會(huì)對(duì)table的block進(jìn)行操作,同時(shí)也對(duì)索引樹的block進(jìn)行維護(hù),那么當(dāng)同一時(shí)間有大量會(huì)話都需要對(duì)索引(或表)的同一個(gè)block做維護(hù)時(shí),就會(huì)產(chǎn)生索引(或表)上面的爭(zhēng)用.當(dāng)出現(xiàn)爭(zhēng)用時(shí),v$session_wait顯示了當(dāng)前的會(huì)話正在等待的event name.
這個(gè)等待事件表明,當(dāng)前的會(huì)話正在等待一個(gè)block上面的事務(wù)槽的分配,可能是table block或index block.
可能的原因有:
解決思路:
小知識(shí)點(diǎn):
在v$lock中若看到某個(gè)會(huì)話正request一個(gè)lmode為4的鎖,其原因之一就可能是ITL等待造成的,其它原因可能是并發(fā)操作主鍵、位圖索引、分布式事務(wù)等.
這個(gè)問(wèn)題一般發(fā)生在表在高并發(fā)insert操作時(shí),等待在字段類型是日期、自增序列的索引block上.因?yàn)閼?yīng)用始終插入的都是最新(high key)的值,導(dǎo)致這些索引一般都是右傾斜增長(zhǎng)的,也就是說(shuō)最近最頻繁的操作都發(fā)生在索引最右邊的那個(gè)葉子塊上,葉子塊的free空間很快被填滿,然后葉子塊要分裂,分裂過(guò)程總要去找free block,index spliter的進(jìn)程會(huì)持有一個(gè)enq:TX鎖,其它并發(fā)insert的進(jìn)程一般也正是需往最右邊的這個(gè)index leaf block去insert數(shù)據(jù),所以都要等待這個(gè)spliter進(jìn)程完成并釋放這個(gè)鎖.(競(jìng)爭(zhēng)更加激烈時(shí),甚至?xí)赽ranch block的split時(shí)產(chǎn)生)
解決思路:? ?
2)event 43822啟用后,對(duì)于root block的split進(jìn)行了增強(qiáng), 不會(huì)超過(guò)5次的index block reclamation,Oracle就會(huì)去申請(qǐng)分配新塊了.
背景知識(shí):
Oracle在索引split時(shí)中尋找可復(fù)用的free block的過(guò)程如下:
Oracle不會(huì)一開始就讓index segment申請(qǐng)分配新的空間(這會(huì)造成index segment的空間過(guò)度增長(zhǎng)) ,而是到該index segment的其它地方搜索是否存在可用的Free Block, 這些Free Block的要求是status是75%-100% Free的, server process會(huì)掃描這些75%-100% Free的block 并確認(rèn)這些block 實(shí)際上是100%空的, 如果找到100% Free Block則使用;如果沒(méi)有則繼續(xù)搜索, 直到所有候選block都被檢查過(guò),這個(gè)行為叫做 probes on index block reclamation.每次尋找空塊并failed ,oracle就會(huì)增加這個(gè)統(tǒng)計(jì)指標(biāo): “failed probes on index block reclamation”.Oracle內(nèi)部機(jī)制會(huì)控制要找多少次,不會(huì)去FULL SCAN所有index block的,failed超過(guò)一定次數(shù)后就會(huì)申請(qǐng)分配新的block.
不能重用的原因有2個(gè):??
在這個(gè)過(guò)程中,Oracle還有機(jī)會(huì)找到的block其實(shí)已經(jīng)是索引結(jié)構(gòu)中的一個(gè)非空block,但是Oracle只會(huì)在splittingand relinking to index structure之后才會(huì)發(fā)現(xiàn)這個(gè)block其實(shí)是illegal的選擇,這個(gè)時(shí)候Oracle會(huì)回滾這個(gè)操作,這個(gè)統(tǒng)計(jì)記錄在‘transaction rollback’ in v$sysstat,然后繼續(xù)尋找另外一個(gè)block.
Oracle進(jìn)行找空塊的過(guò)程中,如果這些塊不在內(nèi)存中,會(huì)增加物理讀,如果這些塊還需要做延遲塊清除或者還要回滾,則需要觸發(fā)更多系統(tǒng)遞歸操作,可見(jiàn),如果“failed probes”過(guò)多,split效率低下時(shí),會(huì)直接導(dǎo)致index contention增加.
TABLE的High WaterMark(即高水位線)標(biāo)識(shí)table segment中已用空間和未用空間的邊界,具體來(lái)講,HWM以上的block的狀態(tài)是:unformattedand have never been used; HWM以下的block的狀態(tài)是:Allocated, but currentlyunformatted and unused、 Formatted and contain data、Formatted and empty because the data was deleted.當(dāng)HWM以下的block都無(wú)空閑空間可以使用時(shí),Oracle會(huì)推進(jìn)HWM來(lái)申請(qǐng)分配新的block到segment里面,而HW enqueue鎖被用來(lái)管理推進(jìn)HWM分配新空間時(shí)的串行操作.
顯而易見(jiàn),當(dāng)高并發(fā)的insert發(fā)生時(shí),甚至表中若有LOB字段時(shí)情況更糟,HWM的推進(jìn)分配新空間的速度趕不上并發(fā)會(huì)話所需空間的速度時(shí),就會(huì)發(fā)生在HW的enq上的等待.
解決思路: ?
這個(gè)等待事件通常說(shuō)明會(huì)話在等待Undo Segment,注意等待的原因一般其實(shí)并不是因?yàn)閁NDO TABLESPACE沒(méi)有空間了,UNDO表空間不足會(huì)直接報(bào)ORA-30036(NOSPACEERRCNT).
造成這個(gè)等待的典型場(chǎng)景有:
解決思路:
本文重要提示:
上述所有隱含參數(shù)的介紹,一方面是為了加深對(duì)Oracle相關(guān)管理機(jī)制的了解,另一方面都是在常規(guī)手段包括應(yīng)用層調(diào)優(yōu)的手段無(wú)法奏效的前提下的應(yīng)急方案,在生產(chǎn)環(huán)境啟用之前請(qǐng)得到Oracle原廠的確認(rèn)與支持,而且在高峰期或問(wèn)題應(yīng)急解決后務(wù)必要取消隱參.
不要隨意在生產(chǎn)環(huán)境使用隱含參數(shù),這是一個(gè)最基本的數(shù)據(jù)庫(kù)運(yùn)維原則!
上面這些問(wèn)題的解決思路其實(shí)都是治標(biāo)不治本的,這些優(yōu)化措施可能能夠幫助你的系統(tǒng)度過(guò)當(dāng)前的系統(tǒng)波峰,但是隨著時(shí)間的推移當(dāng)更大的波峰出現(xiàn)時(shí),問(wèn)題還會(huì)再次發(fā)生.優(yōu)化“對(duì)數(shù)據(jù)庫(kù)的需求”帶來(lái)的效果永遠(yuǎn)大于優(yōu)化“數(shù)據(jù)庫(kù)所能提供的資源”,雖然有時(shí)候優(yōu)化“對(duì)數(shù)據(jù)庫(kù)的需求”的成本投入更高,但是投入與產(chǎn)出一般都是成正比的.從這個(gè)意義上來(lái)講,若應(yīng)用能夠合理控制并發(fā)、系統(tǒng)架構(gòu)中引入緩存層、采用異步隊(duì)列處理機(jī)制、優(yōu)化DB模型設(shè)計(jì)以及SQL寫法等,這才是解決問(wèn)題的根本之道.
文章出處:DBAplus社群
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/4410.html