web-dev-qa-db-ja.com

OSの再起動後、MySQLクエリが10〜100倍遅くなる

MySQLサーバーをUbuntuで実行しています。 MySQLを再起動すると、すべて正常です。ただし、OSを再起動すると、クエリの実行時間が10倍から100倍になります。私が見つけた問題の唯一の「解決策」は、すべてのテーブルでoptimizeを実行することです。その後、すべてが再び正常に実行されます。ただし、OSを再起動するたびにデータベース全体を再構築することは、明らかに非常に手間がかかり、実行可能な長期的なソリューションではありません。

私はOSを再起動します

  1. データベースを照会するすべてのプログラムを停止する
  2. クエリの実行が完了するのを待っています
  3. 実行中stop mysql
  4. サーバーがps -C mysqlおよびps -C mysqldで停止したことを確認する
  5. 実行中reboot

OSの再起動を省略してMySQLを再起動するだけで問題ありません。

追加情報:

  • エラーログには、問題を示すものは何も含まれず、エラーも発生しません。すべてが1、2倍遅いだけです。
  • すべてのテーブルが影響を受けます。私はInnoDBを使用していますが、MyISAMを使用していたときにも非常に同じ問題が発生しました。
  • 通常、MySQLは8 GBのRAMの80%を使用しますが、OSの再起動後は約1 GBしか使用されません。 CPU使用率は、1つのコアの30〜80%から約1%に低下します。
  • 最適化クエリは80%を通常どおり使用しますRAMそしてCPUも通常の値に上がります。

スペック:

  • MySQL 5.5.35-0ubuntu0.12.04.2
  • Ubuntu 12.04.4 LTS
  • 8GB RAM、4 CPUコア

my.cnfファイル:

[client]
port        = 3306
socket      = /var/run/mysqld/mysqld.sock

[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
Nice        = 0

[mysqld]

local-infile=0

user        = mysql
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
port        = 3306
basedir     = /usr
datadir     = /var/lib/mysql
tmpdir      = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking

innodb_file_per_table

innodb_autoinc_lock_mode = 0

innodb_thread_concurrency=8
innodb_buffer_pool_size=6G
innodb_log_file_size=1600M
innodb_additional_mem_pool_size=1M
innodb_log_buffer_size=4M
innodb_flush_log_at_trx_commit=0

innodb_read_io_threads=3000
innodb_write_io_threads=7000
innodb_io_capacity=10000

key_buffer_size     = 1024M
max_allowed_packet  = 16M
thread_stack        = 192K
thread_cache_size       = 8

myisam-recover         = BACKUP

query_cache_limit   = 1M
query_cache_size        = 16M

log_error = /var/log/mysql/error.log

expire_logs_days    = 10
max_binlog_size         = 100M

[mysqldump]
quick
quote-names
max_allowed_packet  = 16M

[mysql]


[isamchk]
key_buffer      = 16M

!includedir /etc/mysql/conf.d/

key_buffer_sizeは1GB、つまり、再起動後に約RAMが使用されます。接続できましたか?

編集:テーブルごとのクエリ実行時間をログに記録すると、4つのテーブルのうち3つを修復した後、修復された3つのテーブルのクエリ時間が依然として非常に長くなることがあります。したがって、すべてのテーブルが壊れているかどうかは完全にはわかりません。たぶん、サーバー全体のパフォーマンスを低下させているのは1つのテーブルだけですか?ただし、これは実際に使用されるリソースの割合が低い場合とは一致しません。

5
Max

OSを再起動すると、以前にオペレーティングシステムのディスクキャッシュ(RAM)に書き込まれたすべてのディスク読み取りが削除されます。再起動すると、オペレーティングシステムはディスクからMySQLデータを読み取る必要があります。これは、キャッシュ(RAM)から読み取るよりも数桁遅いです。

MySQLがディスクからすべてのテーブルデータを読み取り、OSがデータをキャッシュできるようにするため、これを最適化すると「修正」されます。

Linuxは、ほとんどの空きRAM=をディスクキャッシュとして使用します。これは、freeコマンドを使用して確認できます。

[Oracle@ora12c1 ~]$ free
             total       used       free     shared    buffers     cached
Mem:       4050844     840072    3210772          0      97268     349716
-/+ buffers/cache:     393088    3657756
Swap:      4063228          0    4063228
[Oracle@ora12c1 ~]$ 

MySQLを再起動しても、MySQLではなくデータをキャッシュしたオペレーティングシステムであるため、このキャッシュには影響しません。

問題を「修正」するには、OSがディスクからデータを読み取ってキャッシュするように強制する必要があります。これを行うには、Unix ddツールを使用できます。例えば:

dd if=/var/mysql/data/mytable.idb of=/dev/null

ヒント:vmtouchコマンドを使用して、ディスクキャッシュにある特定のファイルの量を確認できます。このコマンドは、ファイルシステムキャッシュからファイルをパージしたり、ファイルをファイルシステムキャッシュに強制的にロードしたりすることもできます。 http://hoytech.com/vmtouch/ を参照してください

6
Philᵀᴹ

Phil がすでに示唆しているように、速度の低下はキャッシュが物理メモリにないために発生するため、キャッシュをウォームアップするか、Linuxにメモリに保存します。

Bill が提案するツールvmtouchがあり、提供されたファイルまたはディレクトリが既にメモリにあるかどうかを示します-そうでない場合-それらを仮想メモリにマップできます。

テーブルファイルがメモリにあるかどうかを確認するには:

$ vmtouch table.ibd
           Files: 1
     Directories: 0
  Resident Pages: 0/28  0/112K  0%

メモリに配置するには:

$ vmtouch -vt table.ibd

十分なメモリがある場合は、ディレクトリ全体を選択できます。

$ vmtouch -dl /var/mysql/db-name
0
kenorb