您好,登錄后才能下訂單哦!
11 月25日,周五晚上,正在家里看電視, 電話響了 ,是一位銀行客戶資深DBA的來電,也是我的好朋友、好兄弟,看來,他遇到麻煩了…
“
遠邦,11月20號晚上例行跑批的時候,在1分鐘內出現了多筆聯機交易超時!當時的CPU不高,內存很富余,沒有換頁。異常的SQL_ID是15vru8xqgdkjf,就是我們的聯機交易會插入的交易報文表,這個表和批量沒有關系。最嚴重的一筆,就是2016-11-20 20:44:04 ~ 20:44:34,時間達到了30秒。這些交易做的事情很簡單,就是INSERT INTO VALUES,插入交易報文表。我已經把ASH dump的相關信息發到你郵箱了,盡快幫忙分析下原因吧。需要說明信息可以再找我…”
細心的同學,可能已經從這段話中發現了很多信息:
? 舉例故障發生已經過去五天了,還可以查么?
? 故障只出現了不到1分鐘,還可以查么?
? 簡單的一筆INSERT INTO VALUES 怎么可能需要30秒呢?
在Oracle中,答案是YES!
而幫助我們完成這項核查任務的正是客戶提到的ASH dump.
接下來這個case的根因分析,可能會顛覆很多人的運維“經驗”,“沒想到,這么做,對高并發的系統的影響這么大啊…”,還可能會有很多人生收獲哦,我們不妨一起往下看吧。
開啟分析之旅
1
ASH科普
打開郵件,不僅只有 awr 報告、 ash 報告,
還有一個表 ash_1120_2040 的dump,即ASH DUMP,真是貼心極了!
這個表實際上是 dba_hist_active_session_history 的備份, 該表按照 10 秒為粒度,記錄數據庫中活動的會話在執行的 SQL 和發生的等待,且不會隨著重啟而丟失。而 gv$active_session_history 則是按秒采樣存儲,但因為是存放在內存中,因此會隨著重啟而丟失,且保存的數量有限 .
這就是 ASH 功能,即活動會話歷史功能。
舉個例子
:
假設一個會話正在運行一條
SQL
語句,從
4
秒到
34
秒,總計
30
秒
。
因為
ASH
功能是按照
10
秒間隔進行采樣,因此,可能在
4
、
14
、
24
、
34
秒總計采集到
4
次,也可能在
5
、
15
、
25
秒采集到
3
次(
34
秒的時候運行結束,因此下一次
35
秒的采集將沒有該會話)
。
2
ASH初探—活動會話趨勢
將 ash_1120_2040 的dump導入電腦后,
立刻發出下列查詢,獲得按時間分布的活動會話個數的趨勢 。
結果繪制為下圖所示 :
可以看到:
? 兩個紅色豎線之間的 30 秒左右,正是出現部分聯機交易超時的時候。
? 但是在出問題前的幾分鐘,即紅色加框部分,活動進程數已經上來了,這個和客戶確認了一下,是批量調起來的時間,批量是多個進程并發處理的
3
交易超時期間進程都在等什么
接下來,我們發出下列查詢,獲得交易超時期間的等待事件
結果如下所示:
可以看到,都是和 RAC global cache 相關的等待 , 需要說明的是,不懂 RAC 也不影響對這個 case 的閱讀和理解,小 y 主要是通過這個 case 傳授給大家核查疑難歷史問題的方法和思路,以及不斷顛覆自己常識的勇氣,才能不斷進步。
可以看到 :
排在第一位的是 gc buffer busy acquire , 表示數據庫集群中的某個節點,如節點 1 向節點 2 請求一個 BLOCK 的時候,節點 1 已經先有人在我前面申請了同樣一個 BLOCK ,所以連申請都是繁忙的, busy acquire 。
這個等待說明什么呢?
兩個或者兩個以上的會話同時申請同一個 BLOCK ,撞上了。
常見原因:
通常和 SQL 的效率有關,如果 SQL 效率夠高,則無需申請那么多 BLOCK ,就不會和其他會話撞在一起同時申請一個 BLOCK 去了。
但在這里,顯然不是 SQL 效率的問題,因為他就是一條簡單的 INSERT INTO VALUES 的語句而已,不存在執行計劃不好的問題。
顯然,在我之前的申請的那個進程,向節點 2 請求 BLOCK 的過程中遇到了異常,導致了問題的發生。
如果是你,接下來該怎么往下分析呢 ?
4
根因分析之分析阻塞源頭
我們做根因分析,常用的手段就是梳理進程之間的關系。找到阻塞的源頭后分析他在做什么,為什么比平時要慢很多,導致了問題的發生。
分析到了這里,也許有同學會問道,那 “我可以查到本節點是哪個會話在我之前申請了 BLOCK 么?我想去看看排在我前面的會話在經歷什么 … ”
答案是 YES!!!
ASH 中的 blocking_session 字段標識了“哪個會話在我之前先行申請了該 BLOCK ”
接下來,我們發出下列查詢,找到某一瞬間,正在等 gc buffer busy acquire 的上百個會話,分別在申請哪些 BLOCK(p1/p2) ,被誰阻塞了 (blocking_session) 。
可以看到,在開始出現問題的時刻,即 20:44:04
節點 1 有 82 個會話申請同一個 BLOCK 在等 gc bufferbusy acquire, 被節點 1 SID 為 3200 的會話阻塞了,即節點 1 SID 為 3200 的會話先于 82 個進程向節點 2 請求。
5
很多人倒在了去挖寶藏的路上…
乘勝追擊,我們看看節點 1SID 為 3200 的會話在等什么,被誰阻塞了呢?
如此遞歸下去,直到我們找到源頭 , 到底是誰在“一夫當關,萬夫莫開呢” …
結果如下:
可以看到:
異常出現了!節點 1 SID 為 3200 的會話在請求收到文件號 47 , BLOCK 號 1540116 的時候,無法快速獲取,等待事件是 gc current blockbusy, 并且這次申請從 20:44:04 到 20:44:24, 持續了 20 秒以上,但是崩潰的是,沒有辦法知道誰是我的阻塞者了 …
是的, ash 是一座寶藏,但是很多人卻倒在了去挖寶藏的路上。
接下來,該怎么往下查呢?到底去往寶藏的路在哪里呢?
很抱歉,小 y 帶著大家走了一遍這條死路,現實中,確實有很多朋友在不斷重復這條死路,不想繼續重復這條死路,想找一個帶路人的,來參加我們的通向高手系列培訓吧。
6
跟隨小y重新出發
其實,作為
IT
技術人員,我們有時往往在處理問題的時候把問題想的復雜了,太注重技巧了,太注重官方文檔的描述,不知不覺中讓自己走進了死胡同。
最簡單的查問題的方法,像說話一樣順著思路往下查就好了,很多問題從官方文檔中無法得到答案的時候,其實,生活可以給我們答案。無招勝有招。
----
中亦科技小
y
(黃遠邦)
小 y 喜歡化繁為簡,既然客戶已經提到,有一筆插入報文表的聯機交易 2016-11-20 20:44:04 ~ 20:44:34 ,時間達到了30秒。那么我們就從這里開始好了…
結果如下所示
可以看到:
SQL_ID 為 '15vru8xqgdkjf' 在ASH中被連續采樣到了4次,說明執行時間大于30秒.與客戶描述完全一致。然后呢?如果是你,怎么接著往下查,不妨思考幾十秒…
7
再一次倒下?
接下來,我們通過 sql_exec_id 即 SQL 的唯一執行標記,來看看這筆超長交易的情況 :
結果如下所示 :
確實,最長的一筆交易,在 04 秒到 24 秒期間,一直在等 ”gc current retry”
“完了,這個等待事件我沒遇到過啊
…
”,好吧,我也沒遇到過,如果是你,你會怎么往下查,此處建議停下來幾分鐘,度娘和
google
或
MOS
一下,看看是否可以獲得繼續往前走的思路呢
…
最后,您是否又倒在了這里呢?請留言告訴小
y…
答案就在后面,什么時候往后翻,由你決定。
8
向生活問路,要答案
其實小 y 也不知道長交易的會話在等的那個人 ” ”gc current retry” 到底是誰,因為“ gc current retry” 這個人,無論在度娘還是 GOOGLE 還是 METALINK 上都找不到任何解釋。
這個時候,小 y 習慣于向生活要答案。
“gc currentretry” ,從字面上,看是請求當前 BLOCK ,但是無法獲取,在 retry. 既然是向節點 2 請求一個 BLOCK ,無法獲取,需要 retry, 那么我們有必要查下節點 2 是誰負責供應這個 BLOCK 呢? 沒錯!就是節點 2 的 LMS 進程!
接下來,我們于情于理,都應該去查下問題期間, LMS 進程在做什么 …
發出下列查詢即可
結果如下圖所示
可以看到,這些 LMS 進程在等 gcs log flush sync, 即 LMS 進程在把一個 BLOCK 傳給其他節點前,需要把這個 BLOCK 在 log buffer 中的改變,刷到磁盤中的在線日志文件,但是很可惜,刷了很長時間都沒有完成。所以沒有辦法快速將 BLOCK 傳輸給節點 1 ,因此節點 1 在不斷 retry. 這里 ” gcs log flush sync” 的阻塞者 2_2633 顯然就是我們所熟悉的 LGWR 進程,即 log buffer 的寫進程。
9
一馬平川
跨過了這道坎,顯然,我們就可以一路南下,一馬平川了!
接下來,看看節點 2 的 LGWR 進程是不是在忙其他事,無暇顧及 LMS 進程的刷日志請求呢?發出下列查詢
結果如下所示:
可以看到:
節點 2 的 LGWR 進程,在等 enq: CF-contention, 即想要去寫控制文件(例如切換日志時需要寫控制文件),但是被其他人領先一步,這個人是節點 1 的 1369 會話。 期間, LGWR 進程傻傻的繼續等控制文件的隊列鎖,但等了幾十秒都無法獲取。
乘勝追擊,發出下列查詢,看看節點 1 的 1369 會話為什么長時間持有控制文件的隊列鎖。
結果如下:
可以看到, sid=1369 是節點 1 的 ckpt 檢查點進程
ckpt 正在進行控制文件的讀寫,因此持有控制文件的鎖。
期間等待事件是控制文件的順序度和并行寫,并且沒有阻塞,而是一直在變化。 正常來說,如果 IO 比較快的話,那么持有控制文件的鎖的時間是非常快的 。
10
根因分析--查IO的來源
進一步檢查
IO
的性能
從 oswatcher 數據可以看到,在問題時段,很多磁盤 busy 100%, 平均響應時間 200 多毫秒, IO 基本上主要是寫 ,但不是所有盤都 100% ,例如 hdiskpower 11 依然是有少量讀寫的 。
檢查大量寫
IO
的來源
檢查 ASH 中的等待事件
結果如下所示:
可以看到是問題時刻,在等 db file parallel write 的進程有 24 個,顯然是 DBWR 進程在等 該數據庫總計 24 個 DBWR 進程,全部處于活動狀態,說明有什么動作觸發了大量刷臟塊的操作。
11
真相大白,誰觸發了大量臟塊的寫操作
檢查 alert 日志,可以看到 alter system archive log all ( current )的命令,該命令必然會觸發 DBWR 大量刷臟塊,導致磁盤在短時間內極忙,導致 HBA 卡帶寬也可能被占滿。
到這里,大家不妨停下思考下,導致是誰執行了這個觸發全量檢查點的 archivelog all(current) 命令呢?
不妨思考幾十秒…
答案就是我們大家所熟悉的 RMAN 備份腳本!
要說明的是,真相和你想的不一樣!不是備份產生的 IO 影響了磁盤繁忙!
因為之前我們看到了,磁盤繁忙 100% 來自于寫,而不是來自于讀! RMAN 主要是讀! 而且如果是 RMAN 的讀 IO 影響磁盤繁忙,那么不可能只影響了 30 秒左右!
因為 RMAN 腳本開始執行時的 alter system archive log all ( current )的命令觸發了 DBWR 大量刷臟塊,導致磁盤很忙,而控制文件和數據文件在一起,導致 ckpt 進程在拿到控制文件隊列鎖后,操作很慢,繼而阻塞了 LGWR 進程, LGWR 進程于是不響應 LMS 進程,最后導致了 GC 等待數十秒,也就是聯機交易大量超時。全量檢查點完成后,交易恢復正常!
怎么再次驗證呢 alter system archivelog .. 的影響呢?
接下來發出下面這條命令來驗證下 :
可以看到, RMAN 就是在最初的 04 秒發起,之后的 43 分 34 秒往后 RMAN 進程都還在,但交易已經恢復正常,也就是說 RMAN 腳本里觸發的全量檢查點和批量并行寫操作產生大量臟塊疊加在一起,是問題的原因 !
為什么以前沒事??
經確認,當天備份提前了,和批量重疊了,但不是因為 RMAN 備份的讀 IO 導致問題,而是因為 RMAN 備份腳本在最開始執行的 alter system archivelog .. 命令觸發的這次全量檢查點和批量并行寫操作產生大量臟塊疊加在一起,導致 30 秒左右,檢查的 INSERT 聯機交易也出現了超時,這才是問題的真相和問題的根本原因!
12
還沒完,你確認這就是問題的真相么?
你確認這就是問題的真相?
歡迎大家踴躍留言,說說你的想法,同時可以加小 y 微信 shadow-huang-bj ,一起加入學習探討群 . 我將在下期(技術人生系列)揭曉答案。
問題原因與經驗總結
故障原因總結:
l
故障的原因在于批量期間,產生大量臟塊
l
ckpt
進程持有控制文件的隊列鎖后,開始進行
IO
操作
l
但期間
rman
備份調用
alter system archive log
的命令,從而觸發
dbwr
進程往數據文件大量的寫,導致磁盤
100% busy.
導致控制文件的
IO
讀寫無法快速完成。
l
由于日志切換,因此
lgwr
進程需要獲得控制文件的隊列鎖,而
ckpt
進程阻塞了
lgwr
進程,
lgwr
進程處于
enq: CF
–
contention
狀態,無法響應
LMS
進程的日志寫情況。
LMS
進程負責節點間的
GC
。因此,
GC
出現問題,
INSERT
語句出現超時
數據中心運維建議:
?
將控制文件和數據文件從底層
RAID
組就分開,放到其他磁盤組
,
避免被
DBWR
寫
IO
和
RMAN
讀
IO
影響。
?
Rman
備份腳本中的
alter system archive log all
命令會導致數據庫做全量檢查點,觸發
DBWR
的大量
IO
操作,期間拖慢整體性能
?
重新評估
alter system archive log all
的替代方式
?
將
RMAN
備份和批量時間錯開
這個案例下來,小
y
希望您至少有如下收獲:
?
Rman
的備份腳本中的
altersystem archivelog ..
命令居然影響這么大
…
?
術很重要,這是基礎!
?
道也很重要,他可以讓你到達更遠的地方
?
當技術里沒有答案的時候,我們可以問生活,上天不會虧待認真、細心和愛思考的人
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。