swap空間不足導致mysql被OOM kill案例
背景:
某機器記憶體256G,安裝2例項mysql,每個 buffer_pool各106G,總計212G;
某套DB晚上10:00左右遷移到該環境,第2天早上10:00左右收到OOM kill簡訊,因swap空間不足一個Mysql例項被強制kill;
該例項mysqld程式沒有被徹底清除,而是變成了殭屍程式,導致後續無法重啟該例項,最後重啟機器才解決。
調查:
上圖為oom kill後的top輸出,因為該mysqld變為殭屍程式故一直沒有釋放記憶體。
mysql的BP設定為 106G,但是其RES分別達到125G和119G,加起來接近機器實體記憶體上限,而機器swap只有7G且被消耗完畢。
至此原因已經很清晰,解決方案也很簡單,將BP調小90G。
注:自調整截至目前超過10天,沒有再發生類似故障。
延伸
1 mysql記憶體開銷
Innodb_buffer_pool_size定義了快取池的大小,但是緩衝池本身需要額外的資料結構進行管理。
比如,緩衝池每個page都需要一個buf_block_t管理,這部分記憶體沒有計入引數。
各種額外消耗加起來約佔整個BP的8%,也有資料說是10%,具體可參看http://mysqlha.blogspot.co.uk/2008/11/innodb-memory-overhead.html。
這些只是global buffer的開銷,加上session buffer,Mysql所需的記憶體只會更高。
2 為什麼會發生swap
首先大致說一下linux的記憶體管理,numa架構下linux記憶體被分為多個node,非numa則只有1個,由pg_data_t描述,每個node又分為3個zone,由zone_struct結構體描述。
每個zone都有active_lru和 inactive_lru,每個lru又各分為anon匿名頁和file cache對映頁連結串列,總計4個LRU;
zone同時定義了pages_low,pages_min和pages_high,當zone可用記憶體小於pages_low時喚醒kswapd回收記憶體,而當其小於pages_min時則以同步方式喚醒kswapd,直到zone可用記憶體達到pages_high為止;
Linux會快取很多資料,譬如page cache和slab cache,這部分記憶體在回收時會先同步到磁碟然後直接重用,而對於其他記憶體頁,諸如使用者態地址空間的匿名頁,以及IPC共享記憶體區的頁,只能將其置換到swap分割槽,不可直接回收。
OS何時回收記憶體?
1 定期回收:kswapd定期喚醒,當zone空閒記憶體小於pages_low則進行頁面回收,小於pages_min則以同步方式回收;
2 直接回收:linux為使用者程式分配記憶體或者建立緩衝區,而當前系統又沒有足夠多實體記憶體時,則linux會進行頁面回收;當OS嘗試記憶體回收後仍無法獲取足夠多的頁面,則呼叫find_bad_process並進行OOM kill;
不管哪種回收方式,最後都呼叫shrink_list(),對4個連結串列的掃描邏輯定義在vmscan.c中的get_scan_count函式內,其變數scan_balance決定了要回收哪個lru的記憶體,大致邏輯如下:
1. 如果系統禁用了swap或者沒有swap空間,則只掃描file based的連結串列,即不進行匿名頁連結串列掃描
if (!sc->may_swap || (get_nr_swap_pages() <= 0)) {
scan_balance = SCAN_FILE;
goto out;
}
2. 如果當前進行的不是全域性頁回收,並且swappiness=0,則不進行匿名頁連結串列掃描
if (!global_reclaim(sc) && !vmscan_swappiness(sc)) {
scan_balance = SCAN_FILE;
goto out;
}
3. 如果是全域性頁回收,並且空閒記憶體和file based連結串列page數目相加都小於zone->pages_high,則進行匿名頁回收,即便swappiness=0,系統也會進行swap
if (global_reclaim(sc)) {
unsigned long zonefile;
unsigned long zonefree;
zonefree = zone_page_state(zone, NR_FREE_PAGES);
zonefile = zone_page_state(zone, NR_ACTIVE_FILE) +
zone_page_state(zone, NR_INACTIVE_FILE);
if (unlikely(zonefile + zonefree <= high_wmark_pages(zone))) {
scan_balance = SCAN_ANON;
goto out;
}
}
4. 如果系統inactive file連結串列比較充足,則不考慮進行匿名頁的回收,即不進行swap
if (!inactive_file_is_low(lruvec)) {
scan_balance = SCAN_FILE;
goto out;
}
至此,我們可以大致瞭解swappiness=0的作用,其並不能完全禁止swap。
何時觸發OOM kill?
當系統記憶體被消耗殆盡,swap分割槽也被填滿的時候,核心無法分配到新的空閒記憶體,便會啟動OOM刪除程式;
其核心呼叫路徑為out_of_memory() – select_bad_process() – oom_kill_process()
其中select_bad_process()負責挑選待殺死的程式,其掃描系統中的每一個程式並呼叫oom_badness(),該API邏輯如下:
1 獲取程式的oom_score_adj,如果其等於OOM_SCORE_ADJ_MIN即-1000則不Kill,該引數由/proc/NNN/ oom_score_adj記錄,可手工修改
adj = (long)p->signal->oom_score_adj;
if (adj == OOM_SCORE_ADJ_MIN) {
task_unlock(p);
return 0;
}
2 根據該程式消耗的記憶體計算分數,如果是root程式則乘以3%,儘量避免其被Kill,最後將points返回
points = get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS) +
atomic_long_read(&p->mm->nr_ptes) + mm_nr_pmds(p->mm);
task_unlock(p);
if (has_capability_noaudit(p, CAP_SYS_ADMIN))
points -= (points * 3) / 100;
select_bad_process()透過比較每一個程式的oom_badness()返回值,找出得分最高且不是執行緒組leader的程式,將其返回給out_of_memory(),由其呼叫oom_kill_process()傳送sigkill訊號進行撲殺。
除了殺死程式,Linux可以選擇在發生OOM時直接panic,當vm.panic_on_oom=1時成立
結束語
至此我們可以大致瞭解swappiness=0的意義,以及OOM kill發生的原因,為避免此行為應儘量留出充足的記憶體給OS,一般應為實體記憶體的20%左右。
參考資料
http://www.ibm.com/developerworks/cn/linux/l-cn-pagerecycle/index.html?ca=dat
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15480802/viewspace-1815985/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SQL Server Profiler(P)導致C盤空間不足SQLServer
- MySQL:MySQL客戶端快取結果導致OOMMySql客戶端快取OOM
- 使用查詢語句導致 RDS 伺服器報硬碟磁碟空間不足伺服器硬碟
- linux 修改swap空間Linux
- LINUX 建立swap空間Linux
- 磁碟空間不足
- MySQL 5.6因為OOM導致資料庫重啟MySqlOOM資料庫
- dotnet X11 棧空間被回收導致呼叫 XPutShmImage 閃退
- MySQL 磁碟空間滿導致表空間相關資料檔案損壞故障處理MySql
- MySQL 執行 Online DDL 操作報錯空間不足?MySql
- Mysql中使用流式查詢避免資料量過大導致OOMMySqlOOM
- oracle rac 打PSU補丁30805461兩個問題(Java版本及空間不足導致失敗)OracleJava
- MySQL空間暴漲150G導致鎖定,發生了什麼MySql
- 【資料庫資料恢復】磁碟空間不足導致sql server錯誤的資料恢復資料庫資料恢復SQLServer
- Oracle目錄由於TFA觸發bug導致jdb檔案未自動清理引起空間不足Oracle
- Linux交換空間swap講解Linux
- mysql的新建索引會導致insert被lockedMySql索引
- Ubuntu空間不足,如何擴容Ubuntu
- MySQL 網路導致的複製報錯案例MySql
- MySQL Online DDL導致全域性鎖表案例分析MySql
- Linux 磁碟掛載和swap空間管理Linux
- ASM空間爆滿導致資料庫掛起ASM資料庫
- boot分割槽剩餘空間不足boot
- redhat6.9增加swap交換空間大小Redhat
- win10備份空間不足怎麼辦_win10備份空間不足如何處理Win10
- 伺服器空間不足怎麼辦伺服器
- Oracle SYSAUX 表空間使用率100% 導致的DB 故障OracleUX
- MySQL空間最佳化(空間清理)MySql
- oracle dg庫資料檔案空間不足Oracle
- Oracle資料庫閃回區空間不足Oracle資料庫
- 雲伺服器空間不足如何解決?伺服器
- Jenkins臨時空間不足處理辦法Jenkins
- MySQL Case-時間問題導致MySQL例項批次當機MySql
- dbms_lob儲存過程導致臨時表空間100%儲存過程
- Linux 中交換空間 (swap)應該分多大才好?Linux
- 恆訊科技講解:空間不足,香港雲伺服器怎麼加空間?伺服器
- 15、MySQL Case-時間問題導致MySQL例項批次當機MySql
- 如何解決Linux磁碟空間過大或不足?Linux
- oracle表空間不足:ORA-01653: unable to extend tableOracle