MySQLのスロークエリログを一覧したりサマライズしたり出来るNata2
というツールを作ったので、MySQL Casual Talks vol.6で発表させてもらった。
id:oranieさんが早速試してみてくれて、書いてくれたブログエントリにたくさんのブクマがついて大変にありがたい限りです。
MySQLのslow query logを可視化するnata2が大変便利そう - iをgに変えるとorangeになることに気づいたoranieの日記
使い方などをもう少し詳しく
発表当時はドキュメントがまったくなくて大変に雑な感じだったり、発表で説明しきれなかった部分もあったので、ここで改めて少し詳しい解説をします。
Nata2とは
パーズされたスロークエリログをHTTP Postで登録し、件数グラフ、スロークエリログの履歴、mysqldumpslow
相当のサマライズなどの表示が出来るウェブアプリケーションです。
スロークエリログを登録するサーバと、パーズやPostを行うクライアントの2つのコンポーネントがあり、クライアントライブラリは2種類の実装があります。
サーバ、クライアントライブラリすべて、Ruby 2.0以降
で動作します。
Nata2 Server
https://github.com/studio3104/nata2
インストール、データベース準備、起動
git clone
$ git clone https://github.com/studio3104/nata2.git
bundle install
$ cd nata2 $ bundle install
スロークエリログを記録しておくデータベースの準備
データベースは、特に理由のない限りはMySQL
をお使いいただくことを推奨します。
テストではsqlite3
を使ったりはしていますが、他のRDBMS
では動作の確認をしていません。
- 設定ファイル
Sequel
のdburl
をconfig.toml
に記述します。
$ cat ./nata2/config.toml dburl = "mysql2://nata:password@localhost/nata2"
MySQL
にNata2
用のユーザを作成
任意。上述の設定ファイルの通りに接続をしたい場合は、以下の様な感じで。
mysql> GRANT ALL ON nata2.* TO 'nata'@'%' IDENTIFIED BY 'password';
- create database
Nata2
用のデータベース、nata2
を作成します。
$ mysql -uroot -p -e'CREATE DATABASE `nata2`'
- テーブル作成
テーブル作成スクリプトを実行します。
$ bin/nata2server_init_database
起動
unicorn
と組み合わせたり、ポートを変えたりなど、環境に合わせて。
以下のコマンドでは、フォアグラウンドで起動し、0.0.0.0:9292
で待ち受けます。
$ bundle exec rackup
スロークエリの登録
http://nata2.server/api/1/:sarvice_name/:host_name/:database_name
なURLに、以下のようなパラメタをPostしてあげるだけです。
後述のクライアントライブラリを使うとラクですが、自前でパーズなどしてからPostすることももちろん可能です。
{ datetime: 1390883951, user: 'user', host: 'localhost', query_time: 2.001227, lock_time: 0.0, rows_sent: 1, rows_examined:0, sql: 'SELECT SLEEP(2)' }
Postパラメタ
user
とhost
以外は必須です。
- datetime
- スロークエリログ発生日時
- エポックタイム
- user
- クエリの実行ユーザ
- 文字列
- host
- どのホストからのクエリか
- 文字列
- query_time
- クエリ実行時間
- 小数
- lock_time
- ロック時間
- 小数
- rows_sent
- 送信された行数
- 整数
- rows_examined
- 処理対象になった行数
- 整数
- sql
- SQL
- 文字列
- 改行文字を含んでも大丈夫
ビュー
- データベース一覧
同じサービスの中に同名のデータベースが登録されている場合、自動的にComplex
の表示の下に複合ビューへのリンクが生成されます。
Database
の表示の下に表示されるリンクは、各データベースの個別のリンクです。
- スロークエリログ履歴
画像は複合ビューです。同一サービス中の同名データベースがマージされて1つのビュー中に表示されています。
グラフはスロークエリログの件数。
- スロークエリログ個別
mysqldumpslow
相当のサマライズ
画面右上で選択された期間で登録されているスロークエリログをサマライズし、クエリの種類ごとに、合計回数順
、合計クエリ実行時間順
、合計ロック時間順
、合計フェッチ行数順
、平均クエリ実行時間順
、平均ロック時間順
、平均フェッチ行数順
に表示します。
画像は合計回数順
。
クライアントの実装について
MySQL
のスロークエリログは、出力されたuse
句以降は、そのデータベースでのスロークエリログだということがわかるが、どのデータベースのスロークエリだったかということをクエリごとに記録してくれない。
そのため、最後のスロークエリログが発生したデータベースを記録しながらファイルをナメていく実装をしています。
なお、Percona Server
はその限りにあらず、schema
というパラメタをクエリごとに記録してくれる。(設定次第?)
nata2-client
https://github.com/studio3104/nata2-client
- 2つのクライアントライブラリのうちの1つ
- SSHとmysql clientで情報を取得
- スロークエリログ収集対象サーバと、SSH、mysqldの接続情報は設定ファイルに記述
- 処理済み行数と、最後のスロークエリログのデータベース名を
sqlite3
に記録しながら実行する - メモリをギリギリまで使いたいMySQLのサーバで
fluentd
を使うのが不安な場合に使う
インストール
$ git clone https://github.com/studio3104/nata2-client.git $ cd nata2-client $ bundle install
設定
config.toml
に以下のように記述します。
# スロークエリログ収集対象ホストとサービス名を指定 [targets] service1 = [ "host1", "host2" ] service2 = [ "host3", "host4" ] # Nata2 ServerのFQDNと待ち受けポートを指定 [nataserver] fqdn = "nata2.server" port = 9292 [default] # 一度の実行で何行処理するか指定 fetch_lines_limit = 10000 # 個別に指定がないホストのSSH接続情報 [default.ssh] username = "root" password = "password" keys = [ "/home/studio3104/.ssh/id_rsa" ] passphrase = "" port = 20022 # 個別に指定がないホストのmysqld接続情報 [default.mysql] username = "nata" password = "nata" port = 13306 # ホストごとの個別のSSH接続情報 # host1の実行時にdefault.sshを上書きする [host1.ssh] username = "satoshi" keys = [ "/home/satoshi/.ssh/id_rsa" ] passphrase = ""
実行
$ bundle exec bin/nata2-client start
fluent-plugin-nata2
https://github.com/studio3104/fluent-plugin-nata2
http://rubygems.org/gems/fluent-plugin-nata2
- 2つのクライアントライブラリのうちの1つ
fluentd
のプラグイン- 2つのプラグインを内包
- パーズされたスロークエリログを
Nata2
にPostするout_nata2
- スロークエリログをtail&パーズして吐き出す
in_mysqlslowquery_ex
- パーズされたスロークエリログを
- 2つのプラグインを内包
out_nata2
パーズされたスロークエリログをNata2
にポストするプラグインです。
登録API(http://nata2.server/api/1/:sarvice_name/:host_name/:database_name
)の:service_name
と:host_name
はtag
から決定されるので、このプラグインに処理が渡るときにはtagの末尾がservicename.hostname
のようになるように設定して、サービス名とホスト名を指定しておく必要があります。
主な設定項目
- server
- 必須
Nata2 Server
のFQDN
を指定します
- port
- 必須
Nata2 Server
の待ち受けポートを指定します
in_mysqlslowquery_ex
fluent-plugin-mysqlslowquery
というプラグインが既に存在しているが、
SQL
の連続する空白文字と改行文字を省いてしまうFluent::TailInput
を継承しているため、最近のfluentd
のtailプラグインで使える機能が使えない- どのデータベースのスロークエリログかわからなくなってしまう問題の対応として、ログを先頭から読む
read_from_head
を有効にして使いたい
- どのデータベースのスロークエリログかわからなくなってしまう問題の対応として、ログを先頭から読む
の理由から、Fluent::NewTailInput
を継承した別のプラグインを書きました。
主な設定項目
pos_file
- オプション(有効推奨)
- ログファイルをどこまで読んだか記録しておくファイル
last_dbname_file
とは異なるパスを指定
last_dbname_file
- オプション(有効推奨)
- 最後に出力したスロークエリログが発生したデータベースを記録しておくファイルパスを指定
pos_file
とは異なるパスを指定
dbname_if_missing_dbname_in_log
- オプション
- スロークエリログからも、
last_dbname_file
からもどのデータベースでのスロークエリログだったかわからなかった場合に使われるデータベース名
format
- 何を指定しても内部で
none
に書き換えられます
- 何を指定しても内部で
read_from_head
- オプション(有効推奨)
- ログを先頭から読みこむ
path
- 必須
- スロークエリログのパス
tag
- 必須
out_nata
との組み合わせで使う場合、tagの末尾をservicename.hostname
のようにして、サービス名とホスト名を指定しておく必要がある
設定例
とりあえずこんな感じで設定しておけばNata2
にスロークエリログが登録されていきます。
ご利用の環境に合わせて適宜変更してご利用ください。
<source> type mysqlslowquery_ex read_from_head path /path/to/slowquery.log tag slowquery.servicename.hostname pos_file /tmp/slowquery.log.pos last_dbname_file /tmp/slowquery.log.lastdb </source> <match slowquery.**> type nata2 remove_tag_prefix slowquery. server nata2.server port 9292 </match>
今後追加したい機能
EXPLAIN
の取得、登録、参照SHOW CREATE TABLE
の取得、登録、参照
など
おわりに
自分がはじめて参加したMySQL Casual Talksはvol3.でした。
登壇されていた皆さんがすごく輝いて見えたのを今でも覚えているし、まさか回を重ねた同会で自分が登壇するだなんて、当時の自分はまったく考えていなかっただろうなーと思います。
機会をくださったid:myfinderさん、会場を提供してくださった日本オラクル様、本当にありがとうございました。