mysqldump缺失-q引數導致mysql被oom幹掉

dbinsight發表於2013-09-12
某日凌晨收到db故障告警,上機器檢查,mysql已經被myqld守護程式重新啟動。檢查/var/log/messages和最近的dmesg發現mysql程式是被oom幹掉了。

資訊大概摘錄如下:
 [13045702.638964] kthread invoked oom-killer: gfp_mask=0xd0, order=1, oomkilladj=0
[13045702.638969] 
[13045702.638969] Call Trace: {oom_kill_process+87}
[13045702.638977]        {out_of_memory+271} {autoremove_wake_function+0}
ERROR: Fatal error found, match ERROR-KEYWORD 'out_of_memory' 
...

 [13045702.716335] Out of Memory: Kill process 25795 (mysqld) score 1591671 and children.
ERROR: Fatal error found, match ERROR-KEYWORD 'Out of Memory' 
[13045702.716359] Out of memory: Killed process 25795 (mysqld).
.....
 [13045702.802080] Out of Memory: Kill process 1907 (mysqld) score 955002 and children.
ERROR: Fatal error found, match ERROR-KEYWORD 'Out of Memory' 
[13045702.802102] Out of memory: Killed process 1907 (mysqld).
....
 [13045762.203463] Out of Memory: Kill process 24544 (mysqld) score 341071 and children.
ERROR: Fatal error found, match ERROR-KEYWORD 'Out of Memory' 
[13045762.203485] Out of memory: Killed process 24544 (mysqld).
[13045762.322333] sap1002 invoked oom-killer: gfp_mask=0x201d2, order=0, oomkilladj=0
.....
 [13045762.479886] Out of Memory: Kill process 19530 (mysqldump) score 93607 and children.
ERROR: Fatal error found, match ERROR-KEYWORD 'Out of Memory' 
[13045762.479907] Out of memory: Killed process 19530 (mysqldump).

由於記憶體不足,系統選擇性的選擇了耗用記憶體大的幾個程式kill掉了。先kill了mysqld,最後才把mysqldump kill掉,這樣有理由懷疑可能是因為mysqldump耗用了大量的記憶體導致的。

在這個db上,每天凌晨會使用mysqldump做單表備份並透過管道進行壓縮。這個備份任務已經部署了超過1年多了。
檢視了後臺採集的OS效能資料,也可以發現在mysqldump啟動直到備份結束,記憶體耗用會上升比較多,這樣可以肯定是因為mysqldump耗用大量記憶體導致此次故障發生。

check備份使用的指令碼,備份的邏輯大概如下:
1:show tables like 'xxx%' 獲取需要備份的表名
2:mysqldump --uxx -pyy  --skip-opt >>

至此問題就比較清晰了,mysqldump由於未使用-q引數導致耗用記憶體過大而導致OOM現象發生。

對mysqldump -q引數的解釋(取自man mysqldump)
  ? --quick, -q

          This option is useful for dumping large tables. It forces mysqldump to retrieve rows for a table from the server a row at a time rather than retrieving the entire row set and buffering it in memory before writing it out.

這個選項被用來dump比較大的表。它強制mysqldump從伺服器一行一行的獲取資料而不是把獲取所有行的資料在輸出之前把它快取到記憶體中。

以下是一個測試,可以看到-q 引數對記憶體耗用的影響:
1:不帶-q引數
top輸出如下:
PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
20010 mysql     15   0 18.0g  17g 4496 S   10 56.6   2765:51 mysqld
27518 mysql     25   0 4227m 4.1g 1048 R  100 13.1   0:33.05 mysqldump
記憶體耗用超過4G
2:帶-q引數
top輸出如下:
PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
20010 mysql     16   0 18.0g  17g 4496 S   84 56.6   2766:12 mysqld
27686 mysql     25   0 11628 1380 1052 R   98  0.0   0:23.20 mysqldump 
記憶體耗用很小,只有幾K

應對方案:
修改備份指令碼,加上-q引數。

到此還沒完,這個備份任務已經部署了超過1年了,為啥到最近才出現此故障呢?
對DB內的資料做了個統計,需要備份表從之前100M/day的資料量突然爆增到4G/day。知會研發跟進問題,最後發現是前端配置更改導致前端不斷重試導致。


體會:
在很多時候,故障的發生是很多因素交織在一起才發生的。碰到問題需要更深一層考慮去探尋問題發生的根本原因。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29154652/viewspace-772671/,如需轉載,請註明出處,否則將追究法律責任。

相關文章