maehachi08 Anything Blog

2012年05月16日
MySQLサーバの空きメモリ容量が枯渇する件

MySQLサーバで発生する空きメモリ容量枯渇問題

※MySQLバージョンなどの差異で仕様が異なる場合があります。
勤務する会社で発生する事象です。check_mem.pl監視のアラートが飛んできて、サーバをチェックしました。

freeコマンドでざっと見た感じでは、freeとbuffersとcachedを足しても2GBもありません。メモリーは8GB積んでます。

# free
             total       used       free     shared    buffers     cached
Mem:       8176932    8079940      96992          0      84368    1382324
-/+ buffers/cache:    6613248    1563684
Swap:      1052248        208    1052040

topコマンドでメモリ使用量別にソートした場合の結果ですが、おかしくないですか?

# top
top - 19:22:25 up 216 days, 22:54,  3 users,  load average: 5.32, 4.30, 3.44
Tasks:  59 total,   1 running,  58 sleeping,   0 stopped,   0 zombie
Cpu(s): 99.2% us,  0.5% sy,  0.0% ni,  0.3% id,  0.0% wa,  0.0% hi,  0.0% si
Mem:   8176932k total,  7940716k used,   236216k free,    81920k buffers
Swap:  1052248k total,      208k used,  1052040k free,  1341524k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
20071 mysql     16   0 2978m 1.2g 5364 S 198.6 15.5 150245:32 mysqld
 1713 root      16   0 74424 8524 1732 S  0.0  0.1   0:59.42 munin-node
 3158 ntp       16   0 18584 5328 4256 S  0.0  0.1   1:48.30 ntpd
  528 root      16   0 55580 3204 1220 S  0.0  0.0   0:00.06 bash
 5335 root      16   0 55580 3168 1196 S  0.0  0.0   0:00.05 bash
25471 root      15   0 55580 3152 1196 S  0.0  0.0   0:00.43 bash
25469 root      16   0 37284 2904 2280 S  0.0  0.0   0:00.10 sshd
  526 root      15   0 37284 2876 2280 S  0.0  0.0   0:00.02 sshd
 5333 root      16   0 37284 2876 2280 S  0.0  0.0   0:00.00 sshd
 3003 root      15   0 58068 1784 1264 S  0.0  0.0   0:00.00 mysql
 3120 root      15   0 21964 1284  872 S  0.0  0.0   0:44.23 sshd
20038 root      19   0 52760 1140  940 S  0.0  0.0   0:00.00 mysqld_safe
 ・
 ・
 ・

一番メモリ消費の多いmysqldでさえ、1.2GBです。
じゃあ多くのメモリ空間は何に消費されているのでしょうか。

犯人はお前だ!


(犯人)な、何を根拠に。。。いい推理だけど、肝心の証拠がありませんわよ?名探偵さん?

(名探偵)あなたは、ここに置いてあったメモリ空間をOSに依頼されて割り当てを受けました。
    しかし、ディスクに書き出さずにそのまま放置することでメモリを解放せずに持ち続けた。
    そうですよね?
    ActiveCachedさん?

(犯人)。。。



キャッシュの詳細は/proc/meminfoをcatするかvmstat -aで確認できます。
ActiveとInactiveについては<a href=http://www.atmarkit.co.jp/flinux/rensai/tantei01/bangai01c.html>ここ</a>が参考になります。
```bash
# cat /proc/meminfo
MemTotal:      8176932 kB
MemFree:        176416 kB
Buffers:         87324 kB
Cached:        1415272 kB
SwapCached:          0 kB
Active:        7241624 kB
Inactive:       512836 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:      8176932 kB
LowFree:        176416 kB
SwapTotal:     1052248 kB
SwapFree:      1052040 kB
Dirty:             252 kB
Writeback:           0 kB
Mapped:        1283680 kB
Slab:           221184 kB
CommitLimit:   5140712 kB
Committed_AS:  3047876 kB
PageTables:       7592 kB
VmallocTotal: 536870911 kB
VmallocUsed:    263412 kB
VmallocChunk: 536607347 kB
HugePages_Total:     0
HugePages_Free:      0
Hugepagesize:     2048 kB

# vmstat -a
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
 r  b   swpd   free  inact active   si   so    bi    bo   in    cs us sy id wa
 4  0    208  69688 558384 7305612    0    0    55   236    1     1 52  1 46  0

キャッシュの解放とワナ


(犯人)ふん、俺様を解放できるものなら解放してみるがいい!!

(名探偵)なに!どういうことだ!?

(犯人)それは解放したら分かるさ。。。

(女①)探偵さん、ActiveCacheを解放してはダメ!

(名探偵)どうしてですか?

(女①)ActiveCacheはディスクに書き出していないデータも含まれるの。
   mysqlサーバで書き出したりなんかしたら、オンメモリのクエリ情報が消えてしまうわ!!

(犯人)そういうことだ!名探偵さん。さて、俺を捕まえることが出来るかな??



ちなみに、キャッシュを解放するためには以下のコマンドを実行します。
ただし、
```bash
# echo 1 > /proc/sys/vm/drop_caches

メモリの空き容量を増やすためには

いかにしてもActiveCacheをディスクに書き出させ、メモリ空間を解放させるかが鍵と思います。
で、これから調査する項目としてはこんな感じですかね。

      ActiveCachedをディスクに書き出させる
      MySQLサーバのクエリキャッシュをディスクに書き出させる

1つ目はsyncコマンドが真っ先に頭をよぎりました!!
2つ目は皆目見当が付いてないです。
まずは2つ目のMySQLサーバのクエリキャッシュについて調べます。
このあたりが参考になります。

■クエリキャッシュ有効/無効確認

mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+
1 row in set (0.00 sec)

■クエリキャッシュ関連の設定

mysql> show status like '%Qcache%';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| Qcache_free_blocks      | 2466      |
| Qcache_free_memory      | 6809352   |
| Qcache_hits             | 228280499 |
| Qcache_inserts          | 449713087 |
| Qcache_lowmem_prunes    | 401896455 |
| Qcache_not_cached       | 53168825  |
| Qcache_queries_in_cache | 4935      |
| Qcache_total_blocks     | 16135     |
+-------------------------+-----------+
8 rows in set (0.00 sec)

クエリキャッシュを削除するには以下SQLを実行。でも危険なので商用ではやめたほうがいいでしょう。

mysql> RESET QUERY CACHE