読者です 読者をやめる 読者になる 読者になる

Studio3104::BLOG.new

uninitialized constant Studio3104 (NameError)

MySQL Casual Talks vol 6.でNata2について発表してきた

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では動作の確認をしていません。

  • 設定ファイル

Sequeldburlconfig.tomlに記述します。

$ cat ./nata2/config.toml
dburl = "mysql2://nata:password@localhost/nata2"
  • MySQLNata2用のユーザを作成

任意。上述の設定ファイルの通りに接続をしたい場合は、以下の様な感じで。

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パラメタ

userhost以外は必須です。

  • datetime
    • スロークエリログ発生日時
    • エポックタイム
  • user
    • クエリの実行ユーザ
    • 文字列
  • host
    • どのホストからのクエリか
    • 文字列
  • query_time
    • クエリ実行時間
    • 小数
  • lock_time
    • ロック時間
    • 小数
  • rows_sent
    • 送信された行数
    • 整数
  • rows_examined
    • 処理対象になった行数
    • 整数
  • sql
    • SQL
    • 文字列
    • 改行文字を含んでも大丈夫

ビュー

  • データベース一覧

同じサービスの中に同名のデータベースが登録されている場合、自動的にComplexの表示の下に複合ビューへのリンクが生成されます。
Databaseの表示の下に表示されるリンクは、各データベースの個別のリンクです。

f:id:studio3104:20140722222126p:plain

  • スロークエリログ履歴

画像は複合ビューです。同一サービス中の同名データベースがマージされて1つのビュー中に表示されています。
グラフはスロークエリログの件数。

f:id:studio3104:20140722221451p:plain

  • スロークエリログ個別

f:id:studio3104:20140722221738p:plain

  • mysqldumpslow相当のサマライズ

画面右上で選択された期間で登録されているスロークエリログをサマライズし、クエリの種類ごとに、合計回数順合計クエリ実行時間順合計ロック時間順合計フェッチ行数順平均クエリ実行時間順平均ロック時間順平均フェッチ行数順に表示します。
画像は合計回数順

f:id:studio3104:20140722221753p:plain

クライアントの実装について

MySQLのスロークエリログは、出力されたuse句以降は、そのデータベースでのスロークエリログだということがわかるが、どのデータベースのスロークエリだったかということをクエリごとに記録してくれない。
そのため、最後のスロークエリログが発生したデータベースを記録しながらファイルをナメていく実装をしています。
なお、Percona Serverはその限りにあらず、schemaというパラメタをクエリごとに記録してくれる。(設定次第?)

nata2-client

https://github.com/studio3104/nata2-client

  • 2つのクライアントライブラリのうちの1つ
  • SSHmysql 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

out_nata2

パーズされたスロークエリログをNata2にポストするプラグインです。
登録API(http://nata2.server/api/1/:sarvice_name/:host_name/:database_name)の:service_name:host_nametagから決定されるので、このプラグインに処理が渡るときにはtagの末尾がservicename.hostnameのようになるように設定して、サービス名とホスト名を指定しておく必要があります。

主な設定項目
  • server
    • 必須
    • Nata2 ServerFQDNを指定します
  • 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さん、会場を提供してくださった日本オラクル様、本当にありがとうございました。