web-dev-qa-db-ja.com

MySQLのスワップ原因を見つける

私のcentos 6.3サーバーには、MySQL 5.5.33データベースがあります。
これには17個のテーブル(15個のInnoDB、2個のMyISAM)と合計670万行のレコードがあります。スキーマをリファクタリングし、遅いログのインデックスを追加しました。私の平均クエリ時間は20〜30ミリ秒です。そして、私のデータベースはうまく機能します。

しかし、3時間ごとに実行されるcronクエリがいくつかあります。インデックスを使用せず、実行速度が非常に遅く、すべてのクエリが約1500〜2000ミリ秒実行されます。新しいインデックスを追加する予定はありません。その場合、多くのインデックスを追加する必要があり、クエリが実行されることは非常にまれです。

データベースサーバーを再起動すると、-通常-スワップがゼロになります。しばらくするとスワッピングが徐々に大きくなっていきます。 13日後、MySQLの650MBのスワップを取得します。このスワッピングの原因を見つけて、パフォーマンスグレードなしでスワッピングを減らしたいと思います。

原因がcronクエリであるか、その他の原因でこのスワップサイズが発生していることを確認します。

私のtop結果:

top - 13:33:01 up 13 days, 11:04,  1 user,  load average: 0.77, 1.02, 1.07
Tasks: 148 total,   1 running, 147 sleeping,   0 stopped,   0 zombie
Cpu(s): 27.4%us,  5.3%sy,  0.0%ni, 59.1%id,  7.8%wa,  0.0%hi,  0.3%si,  0.0%st
Mem:   1020564k total,   854184k used,   166380k free,    73040k buffers
Swap:  2097144k total,   643036k used,  1454108k free,    94000k cached

  PID USER        PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  SWAP COMMAND
 9573 mysql       20   0 2336m 328m 3668 S  7.3 33.0 349:14.25 554m mysqld
15347 examplecom  20   0  219m  32m  10m S  2.7  3.2   0:02.66    0 php-cgi
15343 examplecom  20   0  215m  28m  10m S 10.0  2.9   0:05.80    0 php-cgi
15348 examplecom  20   0  215m  28m  10m S 12.3  2.8   0:03.62    0 php-cgi
15346 examplecom  20   0  215m  28m  10m S  9.6  2.8   0:06.39    0 php-cgi
15350 examplecom  20   0  212m  25m  10m S 10.0  2.6   0:02.19    0 php-cgi
15345 examplecom  20   0  211m  24m  10m S  6.6  2.5   0:04.28    0 php-cgi
15349 examplecom  20   0  209m  22m  10m S  5.3  2.2   0:02.66    0 php-cgi
12771 Apache      20   0  334m 5304 2396 S  0.0  0.5   0:02.53  10m httpd
12763 Apache      20   0  335m 5224 2232 S  0.3  0.5   0:02.33  11m httpd

編集:私は2日前にmysqlサーバーを再起動したので、現在スワップは少ないです。しかし、時間の経過とともに、それは再び大きくなります。 topを作成すると、次のようになります。

top - 23:30:46 up 15 days, 21:01,  1 user,  load average: 0.35, 0.42, 0.42
Mem:   1020564k total,   931052k used,    89512k free,    76412k buffers
Swap:  2097144k total,   280528k used,  1816616k free,   233560k cached

  PID USER        PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  SWAP COMMAND
23088 mysql       20   0 1922m 311m 3440 S  1.0 31.3  50:04.53 143m mysqld
10081 examplecom  20   0  216m  28m  10m S  4.0  2.8   0:01.67    0 php-cgi
10069 examplecom  20   0  215m  27m  10m S  3.3  2.7   0:04.81    0 php-cgi
10070 examplecom  20   0  215m  26m  10m S  8.3  2.7   0:04.75    0 php-cgi
10062 examplecom  20   0  215m  26m  10m S  6.0  2.7   0:06.26    0 php-cgi
10060 examplecom  20   0  214m  25m  10m S  5.3  2.6   0:07.51    0 php-cgi
10074 examplecom  20   0  214m  25m  10m S  6.6  2.6   0:03.01    0 php-cgi
10080 examplecom  20   0  212m  23m  10m S  6.0  2.4   0:01.58    0 php-cgi

私が作るときfree -m私はこれを得ます:

             total       used       free     shared    buffers     cached
Mem:           996        927         68          0         76        219
-/+ buffers/cache:        631        364
Swap:         2047        273       1774

ぼくの /etc/my.cnfファイルの内容:

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
symbolic-links=0
skip-name-resolve

slow_query_log=ON
long_query_time=1.2

innodb_file_per_table

max_allowed_packet=32M
thread_stack=256K
max_allowed_packet=32M
thread_stack=256K
max_connect_errors=100000000
max_connections=600

key_buffer=256M
sort_buffer_size=2M
read_buffer_size=2M
read_rnd_buffer_size=2M

thread_cache_size = 8
tmp_table_size=128M
max_heap_table_size=128M
query_cache_size = 209715200
query_cache_limit = 52428800
join_buffer_size=4M
table_cache=2400
low_priority_updates=1
tmpdir = /var/tmp

query_cache_type = 1

innodb_buffer_pool_size=256M
innodb_additional_mem_pool_size=512K
innodb_log_buffer_size=500K
innodb_thread_concurrency=8

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
3
trante

メモリを過剰に割り当てているようです。より大きなセッションバッファー(tmp_table_size=128M, max_heap_table_size=128Mなど)とともに、比較的多数の接続(600)を許可します。したがって、最悪の場合、600個の並列セッションすべてがMEMORYエンジンの一時テーブルに許可された128Mを使い果たすと、600x128M= 77Gメモリが必要になります。ただし、sort_buffer_size=2Mを使用しても1.2 GBが必要ですが、1 GBしかありません。

スワップが使用されていることは、この場合の驚きではありません。ステータス変数Max_used_connectionsをチェックして、最大600の接続を使用しているかどうかを確認し、max_connections変数を減らします。ステータス変数Created_tmp_disk_tablesおよびCreated_tmp_tablesを確認してください。tmp_table_sizeが劇的に増加しなくなるまで、Created_tmp_disk_tablesを安全に減らすことができます。

また、カーネルオプションvm.swappinessが高すぎないかどうか(100など)を確認して、Linuxがより早くスワップを開始し、メモリが不足した場合により積極的にスワップするようにします。

2