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