李真旭@killdb
oracle ace,雲和恩墨技術專家
個人部落格:www.killdb.com
在墨菲定律裡,我們知道,有可能發生的故障就一定會發生,哪怕需要諸多因素的疊加才可能滿足那複雜的先決條件。在以下案例中,我們抽絲剝繭,細緻入微的追溯最終确定了導緻資料庫rac執行個體崩潰的微小原因。
這是一個真實的客戶案例,可以概括為一條參數引發的血案。現象大緻是某天淩晨某 rac 節點執行個體被重新開機了,通過如下是 alert log 我們可以發現 rac 叢集的節點2執行個體被強行終止掉了,如下是詳細的告警日志資訊:
從上面的日志來看,在2:03分就開始報錯 ora-00600,一直持續到2:39分,lmd0 程序開始報同樣的錯誤;然後接着 lmd0 程序強行把資料庫執行個體終止掉了。。直接搜尋 oracle mos,看上去有點類似這個 bug,不過很容易就可以排除。
bug 14193240 : lms signaled ora-600[kghlkrem1] during beehive load
從日志看,2:03分就開始報錯,然而直到 lmd0 報錯時,執行個體才被終止掉,也就是說 lmd0 報錯才是問題的關鍵。那麼我們首先來分析下 lmd0 程序的 trace 檔案内容,如下所示:
從上面的資訊來看,确實是記憶體 heap 存在錯誤的情況。根據 oracle mos 文檔:
ora-600 [kghlkrem1] on linux using parameter drop_cache on hugepages configuration (1070812.1) 的描述來看,此次故障跟文檔描述基本上一緻,如下:
其中位址 [0x679000020] 後面的内容也均為0,跟文檔描述一樣,其次,文章中提到使用了linux 記憶體釋放機制以及同時啟用了hugepage配置。
根據文檔描述,這應該是 linux bug。通過檢查對比2個節點配置,發現節點2的配置确實不同:
當 drop_caches 設定為3,會觸發 linux 的記憶體清理回收機制,可能出現記憶體錯誤的情況;然而我們檢查配置發現并沒有修改:
是以,我認為是之前人為進行了 echo 3 > /proc/sys/vm/drop_caches 操作來強制釋放記憶體導緻。 通過分析發現隻能檢視到最近幾分鐘的操作記錄,如下:
看操作記錄确實發現了操作,那麼同時檢查作業系統日志也發現了一些蛛絲馬迹,如下:
bug: soft lockup - cpu#1 stuck for 10s! [rel_mem.sh:13887
可以看到也确實出現了 drop_cache 的相關操作。大家注意看上面紅色的地方,提到了是執行了一個 shell 腳本,然後還導緻一共 cpu stuck 了,而且也能看出該腳本是在執行回收 cache 的動作。
我堅持認為客戶環境上肯定進行了強制的記憶體回收,但是客戶說他們沒有進行任何人為操作,不過經過我檢查發現确實有一個 crontab 腳本。
那麼為什麼主機上會部署這樣的腳本呢? 我猜想肯定是作業系統的記憶體使用率看起來很高,通過檢查發現确實如此:
我們可以看到128g的實體記憶體,cache 就占據了 88g 的樣子目前。linux 檔案系統的 cache 分為2種:page cache 和 buffer cache, page cache 是用于檔案,inode 等操作的 cache,而 buffer cache 是用于塊裝置的操作。從上面的資料來看,我們所看到的 free -m 指令中的 cached 88552 全是 page cache。而實際上該資料庫執行個體的記憶體配置設定一共也就40g,且使用的是 linux raw。
我們可以看到,整個主機實體記憶體為128g,而 oracle sga+pga 才40g,另外将近 90g 的記憶體都是 fs cache 所消耗。完全可以調整 linux 的參數去釋放 cache,而不需要使用 echo 這種比較暴力的方式;根據 oracle mos 的幾個文檔的描述,推薦設定如下幾個參數:
sysctl -w vm.min_free_kbytes=4096000
sysctl -w vm.vfs_cache_pressure=200
sysctl -w vm.swappiness=40 (老版本的 linux 是設定 vm.pagecache 參數)
關于 linux cache 的一些知識請參考:
http://www.ibm.com/developerworks/cn/linux/l-cache/
file system’s buffer cache versus direct i/o (文檔 id 462072.1)