您好,登錄后才能下訂單哦!
線上的生產系統,因為一些原因,時不時會出現一些意想不到的性能問題,當緊急問題出現時,我們如果無法立即解決,有時通過調整系統硬件資源是一種快速有效的解決應急方式,確保系統能正常運行后,再做根因分析,從根本上解決問題
;
最近老K遇到了客戶的應急策略導致了數據庫重啟的案例,翻了翻郵件歷史,竟是N年前就已經遇到過了;問題本身不算復雜,然而卻可以造成數據庫直接重啟,影響生產,這里特別分享出來,給大家一個風險提示 ;
今天老K為大家分享的這么一個案例
:
某系統增加新業務,在數據庫正常運行,原業務不停業的情況下,在數據庫上完成版本投產的相關操作,結果投產過程偏慢,應用維護團隊擔心投產窗口無法正常完成投產動作,需要系統維護團隊幫助分析加快投產動作;然而,在針對這一問題應急之后,數據庫卻發生了重啟,反而更嚴重的影響了投產動作。
那么,是誰造成了重啟呢?我們應急過程中做出了什么錯誤的判斷嗎?我們需要怎樣避免再次發生類似的悲劇呢?本次分享從最后的故障出發,給大家帶來一次隱蔽的應急深坑,同時文末也給出我們總結的一些應急手段引入新問題的經驗教訓!
Oracle
數據庫問題,還是找不到原因?
不妨找中亦科技試試,我們將盡最大努力為您找到導致故障和性能問題的根本原因。
問題來了
周六,正是某個客戶的投產日,投產時間為晚間19:30開始,持續到翌日早上九點,老K負責現場支持任務。
投產系統多,七點半剛過,各種咨詢接踵而至,老K正忙的不亦樂乎,電話過來了:“老K,快來這邊幫幫忙看下,應用維護團隊說投產動作比較慢,看看有沒有什么辦法加快下速度?”類似的電話接了不少,問題總要一個一個處理,但是剛剛電話涉及的系統還是比較重要的系統,投產窗口有限,肯定是需要更重視一些,于是答應處理完手邊的這個問題緊接著下一個去看看這個系統;
但是,幾分鐘后電話再次響起:“老K,不好了,這個系統數據庫重啟了!快來看看吧!” 這就尷尬了,難道是因為我沒有及時響應他們的問題,系統就撐不住重啟了?如果真是這樣,那這罪過可就大了!趕緊去到事故現場來處理這個問題。
簡單分析,簡單結論
1
明確情況
問題現場,各路同事都在討論著這事。 這個 系統是一套兩節點的 RAC 數據庫,數據庫版本為 11g ,這次重啟實際上是數據庫兩個節點的實例都發生了重啟;
首先看看 alert 日志里有沒有什么信息顯示:
很顯然,數據庫在 19:41 時被 ASMB 進程給終止了,在終止前產生了一些 trace 文件; ASMB 進程是什么進程呢?顧名思義, ASMB 進程就是數據庫實例與 ASM 實例進行交互的進程,從這里的報錯也可以到, ASMB 已經無法連接到 ASM 實例了;
一般來說,出現這種情況,通常的可能是 CRS 發生了重啟,然后這里我們通過 ps –ef 查看 CRS 關鍵進程發現并未發生過重啟;這樣看來與 ASM 有關;于是我們再看 ASM 的 alert 日志,關鍵部分如下 :
可以看到 ASM 實例發生了重啟,而重啟的原因則是:
參數 parallel_max_servers 被設置為 4505 ,而這個參數值是不合法的,該值的設定范圍應該是 到 3600 之間;在發現了這個錯誤后 CKPT 進程終止了 ASM 實例。
似乎問題就很簡單了, parallel_max_servers 被置為 4505 , ASM 實例終止,進而導致 DB 實例終止 。 那么,這里我們就需要搞清楚幾個問題:
parallel_max_servers
設置范圍是
到
3600
,這是硬性規定嗎?還是說是因為在設定某些值之后導致的?
參數設定錯誤通常報錯即可,為何這里會導致
ASM
實例重啟呢?
修改參數的操作來自于誰呢?與他們的應急操作是否有關系呢?
2
分別突破
1)
parallel_max_servers
參數的限定
對于這種硬性設定,我們不妨先查一下官方手冊,查看該參數是否有上限值:
可以看到,該值設定的上限就是 3600 ;
2)
參數修改為什么導致
ASM
實例重啟呢
?
正常情況下,如果我們在數據庫中的 修改 參數, 修改失敗直接拋錯即可,顯然并不會導致數據庫實例的重啟;
而這里發生的重啟,我們可以看到導致重啟的進程是 CKPT 進程:
我們可以認為, CKPT 進程是數據庫實例的關鍵進程,當它遇到錯誤時,它直接終止了整個實例;
3)
誰觸發了
ASM
實例上參數的改變?
通常來說,修改(調大)parallel_max_servers參數的目的是允許系統啟動更多的并行進程;而對于ASM實例來說,修改這個參數本身似乎并沒有太大的意義,畢竟ASM實例都不會open,基本只服務于Database(可能還有一些監控/管理類的語句);那么誰會來修改ASM實例上的參數呢?難道是應急的時候錯把ASM實例當做Database了?
看到這里,不妨思考一下?原因其實很簡單 …..
3
真相其實很簡單
我們在來看看ASM的日志,相關的信息值得思考:
我們可以看到,在參數調整之前,日志中實例發現了CPU count變成了228,緊接著系統就調整了parallel_max_servers值的大小,隨后報錯宕實例;
這里我們首先需要確認,CPU數的調整會引起parallel_max_servers參數的調整嗎?我們再來看看這個參數的相關屬性,其默認值確實就是與CPU_COUNT有關的,而且參數本身就是可以動態調整的;
很顯然,這里Oracle的代碼中似乎在系統調整CPU進而導致parallel_max_servers參數的動態調整時,忘記了該考慮parallel_max_servers還有一個3600的上限,這應該定義為一個bug;我們上MOS核查也很快能找到這個bug:
問題發生在11.2.0.2和11.2.0.3的版本上,在11.2.0.4版本上已經修復;
原來,在版本投產過程中應用維護團隊發現相關任務的速度達不到預期時,他們就與相關系統負責人溝通,希望通過增加資源的方式來加快其任務的執行速度,于是系統負責人在請示領導后給系統動態增加了內存和CPU(使用的IBM小機,可以動態調整硬件資源),并準備在投產完成后再收回資源,然而在調整CPU的過程中,出現了上述錯誤,導致數據庫重啟,投產動作也受到影響
!
3
那些真相以外的真相
遇到了問題,要想怎么規避這樣的問題,怎么樣總結一套發現類似問題的方法,養成這樣的良好習慣可以幫助我思考的更多更深;
——老K
① 若干疑問
看著問題是得到了圓滿的分析,然而還有不少疑惑縈繞在我的心頭,也是客戶所關注的,所以這里先來解答這些問題;
1. 為什么 Database 實例沒有因為 parallel_max_servers 的參數調整而直接重啟呢?
這里我們可以再回過頭來看 database instance 的 alert 日志信息 :
同樣也看到了 CPUcount 的變化,調整到了 228 ;但是并沒有出現 parallel_max_servers 參數的動態調整,其實這里主要的原因是,在 Database 實例中,我們已經在參數文件中指定了 parallel_max_servers 參數的大小了,在指定了參數的情況下,系統不再根據 CPU 數動態調整 parallel_max_servers 參數的大小;
2. 為什么 ASM 實例啟動時,沒有再因為該參數而無法啟動?
在 ASM 再次重啟的時候是怎么計算 parallel_max_servers 參數值的呢?實際上我們搜索 asm 的 alert 日志發現啟動實例是并沒有設定 parallel_max_servers 參數;而我們手動設定 asm 的 parallel_max_servers 參數值也會報錯:
我們發現,在 ASM 實例中壓根就無法設置這個 parallel_max_servers 參數,哪怕是設定到 spfile 中也不允許;實際上在啟動時不計算、不檢查這個參數也就合乎情理了;
3. 剛剛調整上去的 CPU 我再調回來還會宕機嗎?
我們從原理上看,這里數據庫并不關心 CPU count 是變大還是變小,一次是變十個還是變一個,它都會重新來計算 parallel_max_servers 參數的值,那么顯然,這里如果再次調整 CPU count ,如果不是將 CPU count 調整到足夠小,那么再次調整只要調整后的 CPU count 數計算 parallel_max_servers 參數的值大于 3600 ,問題將再次出現 !
4. 如何預防這樣的問題呢?
已經知道了這是 bug ,那么對應的打上相應的補丁一定是根本的解決之道;
而數據中心 11.2.0.3 版本的系統還非常多,而動態調整 CPU 也是常見動作,統一安裝補丁也需要時間,同時還需要考慮時間窗口,肯定需要一定的周期;那么在此之前我們是否還有臨時的預防之策呢?
根據 bug 文檔描述的 workaround 是手動指定 parallel_max_servers 參數為小于 3600 的值,不過我們上面的核查能很明白的看到, ASM 實例無法調整該參數,看來官方文檔沒有考慮 ASM 實例的情況,也有紕漏,那么我們該怎么辦呢 ?
該如何是好呢?如果是你,你會考慮一些什么來規避這類問題呢?
② 更多思考,更多發現
要從根本上來回答上面的這些問題,其實需要了解數據庫到底是如何計算 parallel_max_servers 參數的;實際上我們可以看看如下描述:
從上述描述我們可以看到影響參數的若干變量,包括:
PARALLEL_THREADS_PER_CPU :該參數基于操作系統,通常是 2;
CPU_COUNT :該參數基于數據庫的實際 CPU 數,但是可以調整;
concurrent_parallel_users :該參數基于實例的內存管理模式配置,默認系數為 1/2/4 不等;
PROCESSES :該參數值來實例啟動時的 PROCESSES 參數;
可以看到, parallel_max_servers 的參數值通過兩方面的計算取 min 值,也就是取自 min(parallel_threads_per_cpu*cpu_count*concurrent_parallel_users * 5,processes-15) ;這兩個方面來看,其中一部分確實與 CPU 有關,而另一方面似乎只與 processes 有關,我們再查 11.2 的 references:
processes 參數的值默認是 100 ;如果沒有人調整過 ASM 實例的 process 參數的值的話,那么這里計算 parallel_max_servers 的值應該是 min( PARALLEL_THREADS_PER_CPU * CPU_COUNT * concurrent_parallel_users * 5,100-15 ) , 這里即使前面計算的值再大,這里計算出來的值也只應該是 85 而已 ,也就遠不會超過 3600 ;
難道 真的是又有誰修改了 ASM 實例的 PROCESSES 參數值嗎?還是官方的 reference 是錯誤的呢?如果是你,你會怎么進一步核查這個參數呢?
③ 最后一部分真相
遇到這樣的情況,我們首先檢查并沒有發現兩個節點 alert 日志存在修改記錄;那么難道 reference 真的有誤?事實上我們看的是 11.2 的 reference ,當前的 11.2.0.3 版本發布時間在 reference 之后很久,我們不妨再通過 MOS 核查確認 processes 值默認值的計算方法:
在 MOS 文檔 “ 升級到 11.2.0.3/11.2.04 Grid/ASM 所需要知道的事 ” 中指出, ASM 的 processes 參數的默認值計算是“ available CPU cores * 80 + 40 ”,當然,這里 processes 參數不會隨著 CPU 數動態改變,只會在實例啟動時計算;
我們截取之前時段 AWR 報告中拿到的 CPU cores 數 :
那么這里, parallel_max_servers 的值計算就是:
min(PARALLEL_THREADS_PER_CPU*CPU_COUNT*concurrent_parallel_users*5,last_CPU_cores*80+40-15)
代入實際值即為:
min
(
2*228*4*5, 56*80+40-15
)即
后續針對所有11.2.0.3,打上對應的補丁,避免再次中招;
在補丁打上之前,在database實例確保手動設置parallel_max_servers為小于3600的值,在ASM實例設置processes值為小于3600的值;
如無必要,我們在沒有充足理由調整系統CPU/內存的時候,不要輕易調整系統資源
;
⑤ 真的需要調整CPU嗎?
后續再了解整個情況后,我們再回過頭看系統投產過程中所謂慢的情況,其實只是大量新插入記錄的表未及時收集統計信息導致執行計劃不夠好而造成的執行緩慢;雖然當時 CPU 使用率相較之前確實偏高,但是在這種情況下,不通過收集統計信息,重新執行語句的情況下,通過增加 CPU/ 內存這兩種常用的應急手段實際上毫無幫助;在本次 CASE 中,增加 CPU 的動作反而造成了數據庫宕機!
我們遭遇了什么
我們再來回顧整個事情的前后,以及數據庫本身的動作:
應用團隊認為
SQL
執行緩慢,系統
CPU
使用率較高,建議擴容
CPU/
內存;
在沒有及時分析問題根本原因的情況下,滿足應用團隊需求擴容系統
CPU/
內存,其中
CPU
數擴容到
228
;
數據庫發現
CPU
擴容到
228
,
Database
實例因為手動設置了
parallel_max_servers
參數,不再調整該參數;
ASM
實例沒有設置
parallel_max_servers
參數,于是在代碼中調整了
parallel_max_servers
參數;
調整的目標值是
min(PARALLEL_THREADS_PER_CPU*CPU_COUNT*concurrent_parallel_users*5,last_CPU_cores*80+40-15)
,即
min
(
2*228*4*5, 56*80+40-15
)即
min(9120,4505)=4505
;
CKPT
進程在設置該值之前,因為遭遇
bug
,未能校驗
4505
值是否超過了
parallel_max_servers
的硬性上限值
3600
;
CKPT
進程在設置
parallel_max_servers
值為
4505
時,遭遇錯誤
ora-00068
;
CKPT
作為系統關鍵進程,遇到無法完成的錯誤,終止
ASM
實例;
ASM
實例終止后,
Database
實例無法訪問
ASM
,同時終止;
CRS
發現
Database
實例和
ASM
實例都終止,于是恢復
ASM
實例和
Database
實例;
在再次啟動
ASM
實例時,不需要考慮
parallel_max_servers
參數,
ASM
實例正常啟動,
Database
實例正常啟動;整個重啟完成。
從這里看,一個看似有益無害、多多益善的決定,讓一套系統發生了重啟,所以,應急需謹慎,最好做到對癥下藥,避免出現意想不到的結果。
風險提示
在數據庫版本為 11.2.0.2/11.2.0.3 的情況下,對于數據庫實例,建議手動設置 parallel_max_servers 參數,對于 ASM 實例,建議手動設置 processes 值為小于 3600 的值,避免出現 CPU 數量過高的情況下,動態調整 CPU 數造成的 Database/ASM 實例重啟的情況。
本文轉載于中亦安圖
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。