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