b.l0g.jp     About     Archive     Feed

MySQLの監視はCacti+Percona Monitoring Pluginsがおすすめ(監視サーバ構築編)

MySQLをリソース監視する仕組みにはいくつかあるが、対象のMySQLサーバが5台以上ある場合はCactiがおすすめ。導入のしやすさだけでMuninを選ぶ人が多い気がするが、その選択基準は間違っている!

 

Cactiのいいとこわるいとこ

  • 多数のグラフを見やすく並べられる
  • muninと比べて多数のサーバから軽快に情報を収集・表示できる
  • 監視対象には、MySQLのユーザを追加するだけでかなりの項目数を監視できる
  • データの保存にデータベースが必須だったりしてセットアップがやや面倒
  • 慣れるまで監視プラグインを書くのに手間取る

Muninのいいとこわるいとこ

  • 監視プラグインを書くのが簡単
  • 監視サーバにデータベースなどが必要なく、セットアップが簡単
  • グラフの並び方などが固定で、比較などがしにくい
  • 監視対象にプラグインを入れなければならず、台数が多いとそれだけ手間が増える
  • 監視対象が増えると監視サーバの負荷が急激にあがるので、あまり多数のサーバは監視できない

そんなわけで、CentOS 6.2上にCactiの監視サーバをセットアップし、Percona Monitoring Plugins for Cactiを使ってMySQLサーバ(CentOSまたはUbuntu)のリソース監視を始めるまでの手順。その1は監視サーバのセットアップ編。

RPMforgeのリポジトリ追加

RPMforgeリポジトリには最新のCactiが含まれているため、これを導入する。

  
$ wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm
  
$ sudo rpm -ihv rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm
  
$ sudo yum -y update rpmforge-release
  

/etc/yum.repos.d/rpmforge.repo ファイルをエディタで開き、 enabled = 0 にする。これで、オプションを付けないとRPMforgeはリポジトリとして有効にならないようになる。

Cactiのインストール

Cactiと、あわせて必要なnet-snmpやhttpd、MySQLなどをインストール。

  
$ sudo yum install -enablerepo=rpmforge cacti net-snmp-utils mysql-server
  

指定したもの以外に、依存関係上httpd, mysql, perl, php, rrdtoolなどもインストールされる。

MySQLの設定

Cactiが取得した情報を格納するためのMySQLを設定する。ここでは最低限必要な設定だけを記述するが、CentOS 6.2のMySQLの/etc/my.cnfは非常にシンプルなので、必要に応じてパラメータを指定すること。

[mysqld]セクションに以下を追加

  
skip-character-set-client-handshake
  
character-set-server = utf8
  
collation-server = utf8\_general\_ci
  
init-connect = SET NAMES utf8
  

(2012.05.29) default-character-setは不要とnippondanjiさんからはてブコメントで指摘をいただいたので削除。直々にご指摘とは恐縮です。

ここでMySQLを再起動する。

  
$ sudo /etc/init.d/mysqld restart
  

statusコマンドで、charactersetがutf8であることを確認。

  
mysql> status;
  
(略)
  
Server characterset: utf8
  
Db characterset: utf8
  
Client characterset: utf8
  
Conn. characterset: utf8
  
(略)
  

Cactiのドキュメントにしたがって、Cactiで使用するMySQLの設定を行う。

  
$ mysqladmin -user=root create cacti
  
$ mysql cacti < cacti.sql
  
$ mysql -user=root mysql
  
mysql> grant all on cacti.* to ユーザ名@localhost identified by 'パスワード';
  
mysql> flush privileges;
  

Apache/PHPの設定

/var/www/cacti/include/config.php を上の項で作成したユーザに合わせて編集する。

  
$database_type = "mysql";
  
$database_default = "cacti";
  
$database_hostname = "localhost"; # DBサーバのホスト名
  
$database_username = "cactiuser"; # 上の項で作成したユーザ
  
$database_password = "cactipassword"; # 上の項で設定したパスワード
  

/etc/httpd/conf.d/cacti.php が存在することを確認する。他のホストからCactiにアクセスする際は、以下の行を追加してhttpdを再起動する。

  
allow from 127.0.0.1
  
allow from IPアドレス # 追記
  

Cactiのドキュメントを参考に、/etc/php.ini および /etc/php.d/*.ini の記述を確認。設定を変更したら、Apacheを再起動する。

  
$ sudo /etc/init.d/httpd restart
  

iptablesの設定

CentOS 6.2ではデフォルトでpingやSSHしか応答できないようにされているようなので、/etc/sysconfig/iptables に以下を追加してhttpのアクセスが可能なようにする。

  
-A INPUT -m state -state NEW -m tcp -p tcp -dport 80 -j ACCEPT
  

iptablesを再起動

  
$ sudo /etc/init.d/iptables restart
  

設定完了

Cactiをインストールした際に /etc/cron.d/cacti が既に作成されているので、この時点で5分おきに情報収集が始まっている。

http://CactiサーバのIPアドレス/cacti を開くと、まずインストールの確認ウィザードが開始される。

ここまでの設定を改めて確認されるだけなので、基本的にはNextを押していけばいい。各種ツールのパスを確認される画面が最後にあるが、ここでパスが見つからない場合は手動でパスを入力するか、不足しているツールをインストールして再度試すべし。

この後ログイン画面が表示され、ユーザ名 admin 、 パスワード admin でログイン可能で、すぐにパスワードの変更を促されるので画面の指示に従って変更する。

Percona Monitoring Plugin for Cactiの導入

PerconaからPercona monitoring pluginsをダウンロードし、ファイルを展開する。

  
$ tar zxvf percona-monitoring-plugins-1.0.0.tar.gz
  
$ cd percona-monitoring-plugins-1.0.0/cacti/scripts
  
$ sudo cp ss\_get\_by\_ssh.php ss\_get\_mysql\_stats.php /var/www/cacti/scripts/
  

監視対象のMySQLにログインする際のアカウント情報を ss_get_mysql_stats.php に書き込む。

  
$mysql_user = 'cactiuser'; # 監視対象にログインする際のMySQLユーザ
  
$mysql_pass = 'cactiuser'; # 監視対象にログインする際のパスワード
  

Cacti管理画面からImport/Export → Import templatesを選択し、Import Template from Local Fileで以下を指定してImportボタンを押し、テンプレートファイルを読み込ませる。

  
percona-monitoring-plugins-1.0.0/cacti/templates/cacti\_host\_template\_percona\_mysql\_server\_ht_0.8.6i-sver1.0.0.xml
  

成功すると、それぞれの監視項目に対応したテンプレートごとに[success]と表示される。

これでMySQLサーバを監視するための監視サーバの準備は完了。

(2012.05.28追記) 監視対象側の設定についても書いたので、続けてどうぞ。

MySQLの監視はCacti+Percona Monitoring Pluginsがおすすめ(監視対象設定編)

MyISAMを使っている時key_buffer_sizeは大きくし過ぎてもいけない

MyISAMのみを使っているMySQLサーバで、key_buffer_sizeのサイズは大きくても小さくてもダメですよ、という例。

その前にちょっと復習。MySQLの主なストレージエンジンといえばMyISAMとInnoDBだが、データやインデックスのキャッシュの仕組みには、

  • InnoDB : インデックス、データともMySQLがキャッシュ管理する(innodb_buffer_pool_sizeで設定)
  • MyISAM : インデックスはMySQLがキャッシュ管理する(key_buffer_sizeで大きさを設定)。データはOSのキャッシュ機構におまかせ

という違いがある。

ものすごく簡単に言えば、InnoDBの場合はなるべく大きな innodb_buffer_pool_size を設定してやれば、インデックスかデータかに関わらずメモリ上にキャッシュされて高速化が図れる可能性がある。一方MyISAMの場合、key_buffer_size を大きくしてもインデックスしかキャッシュされないので、OSがデータ部分をキャッシュするメモリ(つまりMySQLに割り当ててないメモリ)もある程度確保しておく必要がある。この辺りのことはMySQLのドキュメントには以下のように書かれている。

innodb_buffer_pool_size

専用サーバの場合物理メモリの80%。

MySQL 5.1 リファレンスマニュアル 13.5.4. InnoDB 起動オプションとシステム変数

key_buffer_size

「一般的には、マシンのメモリ使用率 25 % の値であることが好ましい」一方で

「Key_reads/Key_read_requests の比率は、0.01 より小さいことが望ましい」つまり

99.9%がキャッシュされていることが望ましいということ。

MySQL 5.1 リファレンスマニュアル 4.2.3. システム変数

とある参照用のスレーブ(MyISAMのみ使用)で、アクセス数とともにデータ量も増加して、インデックスがメモリに乗りきらず、Key_reads/Key_read_requests (以下key bufferヒット率という)が80%台まで落ちてしまっていた。

メモリを増設してkey_buffer_sizeを調子に乗ってでっかく取ってみたが、key bufferヒット率は99.9%になったものの、相変わらずディスクからの読み出しは多い。ここで、上に書いた仕組みに思い当たり、データ部分をキャッシュするOS用のメモリが不足しているのでは、と思って一旦key_buffer_sizeを少し減らしてみた。

  • インデックスのサイズ : 22GB
  • 従来 key_buffer_size : 4GB (OS物理メモリ12GB)
  • 増強後 key_buffer_size : 12GB (OS物理メモリ24GB)
  • その後 key_buffer_size : 8GB (OS物理メモリ24GB)

すると一目瞭然、以下のグラフの青枠部のようにディスクからの読み出しは半分以下に減った(赤線が設定を変更した時点)。

key_buffer_sizeを大きくしたからといってパフォーマンスが上がるというわけではないのである。上の例から分かるように、全インデックスがメモリに乗らなくても、よく使うインデックスがほぼメモリに乗っていれば問題ない。常にkey bufferヒット率が最大になり、ディスク読み出しが最小になる key_buffer_size を探ることが必要ということだ。サイズはオンラインでも変更できる。ただし、コマンドを実行するとkey bufferの中身は一旦空になり、改めてキャッシュが構築されるため一時的にディスクIOが大量に発生するので注意(停止できるサーバならキャッシュウォームアップをした方がよい)。

  
mysql> set global key\_buffer\_size = バイトでのサイズ(1GBなら1073741824);
  

確認は show variables で。以下は4GBの例。

  
mysql> show variables like 'key\_buffer\_size';
  
+------+----+
  
| Variable_name | Value |
  
+------+----+
  
| key\_buffer\_size | 4294967296 |
  
+------+----+
  
1 row in set (0.00 sec)
  

そもそもインデックスがでか過ぎるのでシェイプアップすべきとか、テーブル分割を考えるべきといった別の解決方法も考えられるのだが、わかりやすいグラフが取れたのでひとつの例として。

MySQLエラーログに出てきたエラーコードのとっかかり

MySQLのエラーログに記録されるエラーコードは、MySQL自体が判断して表示するものと、OSが返したエラーコードをMySQLが表示しているものとの2種類に分けられる。それぞれまずどう調べ始めるか、という話。MySQL Performance Blogのエントリに、後で自分の役に立つように情報を加えてみた。

例えば、レプリケーションがうまくいかない時に表示される

  
Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position'
  

というエラーの「1236」は、MySQL自体が判断した結果なので、以下のサイトで一覧が見られる。というか、表示されているままで、それ以上の情報はエラーログの前後や他のログ(OSログなど)を確認するしかない。

4.1

MySQL 4.1 リファレンスマニュアル 12.1. 返されるエラー

5.0/5.1/5.5 (バージョン部分を変えるだけで全部URLは同じ)

MySQL 5.0 Reference Manual C.3. Server Error Codes and Messages

MySQL 5.0 Reference Manual C.4. Client Error Codes and Messages

一方、以下のようなエラーの場合、

  
120326 16:56:45 [ERROR] /usr/sbin/mysqld: Incorrect key file for table '/tmp/#sql\_21b2\_0.MYI'; try to repair it
  
120326 16:56:45 [ERROR] Got an error from unknown thread, storage/myisam/mi_write.c:223
  
120326 16:56:45 [ERROR] /usr/sbin/mysqld: Sort aborted: Error writing file '/tmp/MYK74Kpi' (Errcode: 28)
  

エラーコードを調べないままだと、ファイルへの書き出しで失敗したことまでは分かっても、その先何が起きているのかは分からない。ここで、「Errcode: 28」は、OSが返しているエラーを表示している。これがどのような意味かは、perrorコマンドで分かる。

  
$ perror 28
  
OS error code 28: No space left on device
  

エラーログだけでは判断がつかないが、エラーコード28の意味が分かると、単純な問題であることが判明する。MyISAMはディスクがいっぱいであるというエラーを正しく扱わないという問題があるので、このようなことになる。

perrorコマンド、MySQLに付属している小ネタ的コマンドだが、OSエラーコードをそのまま表示する他のソフトウェアのエラーログを見る時にも役立ちそうだ。