您好,登錄后才能下訂單哦!
前言 某大型國有銀行一套關鍵系統10g升級到11g,老K負責升級后第一天早上的運行保障;在升級前甲方客戶已經先后做了各種測試,以保證升級后不會存在任何性能問題。然而,事與愿違,老K剛到現場,客戶應用團隊就已經反饋到客戶說批量慢了一段時間,根據應用日志與現場負責協助升級的友商DBA的核查,初步定位問題為升級后使用的存儲變慢導致的導出緩慢,拖慢了批量的執行時間。對于這一結論,客戶在調動存儲相關工程師進行核查的同時,還存在疑惑,于是老K便開始參與這一問題的追查;現在問題就可以描述為:oracle從10g升級到11g后,導入操作變慢。
因為是升級前后導入的效率變化,于是老K首先將生產系統分別在10g和11g的環境下導入的日志來進行對比,主要核對導入的時間點后再進一步查看相關時間點數據庫的狀態。然而,在看過兩個日志后,老K就有了自己的疑惑,于是,我就啟動自己的虛擬機,開始自己的驗證探索之旅。
上面兩圖是我在自己的虛擬機上直接測試導入得到的導入日志文件,細心的你在看完下圖之后,是否也發現了一些疑惑呢?老K提示:
老K提示:
1.導入時啟用了并行(并行為6,大于表的個數)
2.導入時使用了content=data_only(說明數據庫中原來已經有了表的定義)
3.導入的表中存在分區表(A1,A2,A3共計24個分區)和非分區表(A6)
02分析中。。。如圖所示,表A6比較大,有超過500萬條記錄(而且這里老K還在A6表上建了索引,在導入時還需要維護A6表的索引,其他表則沒有索引),而其他所有的表占用空間加起來也不過300M大小而已。在10g的日志中,A6表的日志記錄寫在了最后一行,而在11g的日志中則出現在了第四行。
正常來說,使用數據泵導入/導出多個表時,會在導入/導出完成時在日志中打出相應表的信息,如果這里A6表作為一個大表,卻相較于其他表先完成導入操作,我們就可以懷疑分區表和非分區表同時導入時,11g數據泵的機制是存在問題的,特別是在對比了10g的導入情況后。
03猜測&驗證
上面梳理出疑惑,我們應該怎么去驗證呢?如果我們是正在執行導入/導出的操作,我們可以attach到導入/導出任務中進行實時觀察;而如果是導入/導出已經完成了,那我們就需要從數據庫的歷史性能視圖中去尋找答案了(這里我們主要針對11g數據庫進行驗證)。
首先,我們先來通過v$active_session_history視圖來查看導入的整體情況:
這里使用v$active_session_history視圖來核查,每秒做一次采樣發現,導入期間,數據庫確實啟動了6個并行進程(worker),其中DW00進程采樣次數最多,但是各進程的最早采樣到的時間和最后采樣到的時間相差無幾,都是從12:36左右到12:51;顯然,這個過程中有部分worker進程是空閑的;
那么,是不是分區表導入存在問題呢?
我們先來分析分區表(以A1為例)的導入過程:
通過上面結果,我們能看到一個特征,就A1表而言,其各個分區的導入散落在不同的DW進程上,但是從采樣的最大最小時間上看,沒有重合時間區域,也就是說,在目前DATAPUMP啟動了6個并行來導入4個表的時候,看起來分區表A1表并沒有做到多個分區并行導入,同樣我們核查A2、A3表的導入情況:
得出結論如下:導入時,雖然并行度是6,只導入4個表(含分區表)的情況下,所有的表的多個分區間沒有并行地導入,至少有個兩個DW進程是空閑的(實時attach到導入進程監控時更是一目了然)。
此類情況是不是與我們以往的經驗相違背呢?
知識點:
1.數據泵導入時,并行主要是通過多個進程分別導入不同的表來提高導入速度的,而不同的分區作為不同的segment一般也被當做不同的表來處理;
2.數據泵導入時,默認使用的是insert append的方式,也就是說在導入時會持有對象的表鎖;
本次的導入好像就是與第一條有所不符,導入時在存在空閑進程的情況下,同一個表的不同分區并沒有做到并行,那是為什么呢?我們需要注意到我們在前面提到的幾個導入特征,其中一個就是,我們使用了content=data_only; 使用這個參數就意味著,當前數據庫中已經有了該分區表的定義,只是將數據導入到已存在的表中去,在數據庫中已經存在分區表的定義而需要向其中導入數據時,則可能會遇到的一種情況是,數據庫中分區表的定義與DUMP文件中分區表的定義不一致(比如分區鍵不一致),導致DUMP文件中的分區無法與數據庫中的已有分區一一對應,而無法做到一一對應就意味著,如果啟動多個WORKER同時導入一個表的不同分區,不同WORKER就有可能會同時向一個目標分區中執行insert append操作,前面提到,insert append操作會持有行鎖,這樣最后會出現導入worker間的互相阻塞的情況,而且有可能形成死鎖,所以oracle較新的版本中,在導入已存在分區表時(使用了參數content=data_only等),同一表的多個分區是順序導入的(雖然有可能是通過不同的worker來執行)。
04疑問&解答那么10g數據庫的導入是不是也是這樣呢?我們用同樣方法來測試觀察,可以發現10g數據庫的導入也是如此,那么客戶在10g、11g環境中導入的數據、表的定義、導入命令,都沒有變化,看起來并行+metadata_only并不是問題所在,那么真正的問題在哪里呢?我再次回到最開始的問題:
在10g的日志中,A6表的日志記錄寫在了最后一行,而在11g的日志中則出現在了第四行,也就是說,在10g中,A6表是最后完成的,而在11g中A6表卻在A1、A2、A3表的大部分分區完成前已經完成了,是A1、A2、A3表的導入進程在等待什么嗎?
還是要回到v$active_session_history視圖上來:
可以看到,A6導入時間大約從12:36持續到12:49,包含索引維護
而在此期間其他活動的會話中,各分區表只導入了一個分區(即各表導入的第一個分區),而且各WORKER在導入完第一個分區后(12:37:32~12:42:17)并沒有異常等待,而是處于空閑狀態。
我們再回顧一下各個表的導入情況:
可以看到,各個表在導完第一個分區后,出現長時間的停頓,一直等到非分區表導入完,才繼續后續的分區導入;
結合各worker的狀態及各表導入的時間狀態以及前面的結論我們可以確認一點:
在分區表和非分區表同時導入,而且是數據庫中表定義已經存在(使用content=metadata_only等參數)時,分區表需要逐個導入無法使用并行,而在所有分區表分別導完第一個分區后,需要等待所有的非分區表導入完成,才能繼續后面的分區表的分區導入,進而影響導入進度。
而以上問題在10g數據泵中不存在,宇宙行客戶所遇到的問題正是這個問題,升級后多花費的時間也基本上就是單個非分區表導入的時間。以上問題已經提交的ORACLE官方并確認為11g導入的調度機制問題,目前正在開發解決中。
05我們遇到了什么
看看我們遇到了什么問題吧:
1.在10g中,我們使用并行導入分區表和非分區表,并且目標庫中已經有了表的定義,于是我們加上了content=data_only參數;
2.導入的過程中,分區表的各個分區逐個導入,在并行進程足夠多的時候各個表之間實現并行導入;
3.升級到11g以后,各分區表僅僅導入第一個分區,然后開始等待;
4.非分區表導入完成后,各分區表繼續完成導入。
而現在我們知道了,多花費的時間就是第三步的時間,在10g環境先,非分區表可以與分區表并行導入,而到了11g環境中,非分區表只能與分區表導入的第一個分區并行導入;假設,我們需要導入的是一個超大的非分區表和3個分區表,每個分區表3個分區,各分區大小一致,如果單獨導所有的分區表需要1個小時,單獨導所有非分區表需要1個小時,啟用4個并行,在10g的環境里,理想情況下只需要1個小時即可導入完成(以導入最慢的非分區表導入完成,即整體導入完),而在11g的環境中,則需要1個小時+3/4個小時(即105分鐘)。
我們可以做什么:
當我們需要追求導入的效率時:
1.導入分區表時盡量避免使用content=data_only或table_exists_action=appen/truncate的方式,如果已有表的數據量不大,而且dump中表的結構也與已存表的結構一致,我們不妨先存留已有表的數據,再使用table_exists_action=replace的方式;
2.如果導入分區表無法避免使用content=data_only或table_exists_action=appen/truncate,那么我們建議分區表和非分區表分開導入。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。