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