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

Railsでpt-query-digestのexplainがエラーになるので雑に対応した

MySQLのクエリ解析をやろうとDBサーバでtcpdumpでパケットキャプチャとって、

tcpdump -s 65535 -x -nn -q -tttt -i eth0 port 3306 > /tmp/mysql_pcap.txt

explainオプション付きでpt-query-digestを実行してみたんだけど、

pt-query-digest --type tcpdump --explain "h=localhost,u=root,p=xxxxx" /tmp/mysql_pcap.txt

なんかexplainがコケる。

# Tables
#    SHOW TABLE STATUS LIKE 'users'\G
#    SHOW CREATE TABLE `users`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT `users`.* FROM `users`  WHERE `users`.`id` IN (57297, 205043)\G
# EXPLAIN failed: DBD::mysql::st execute failed: No database selected [for Statement "EXPLAIN /*!50100 PARTITIONS */ SELECT `users`.* FROM `users`  WHERE `users`.`id` IN (57297, 205043)"] at /usr/bin/pt-query-digest line 7678.

ちゃんと処理を追ってないけど、Railsはコネクション張りっぱなし系だからdatabaseが特定出来てないのかな。
databaseが1つだけの場合はオプションで接続先を指定してやればいけそう。

pt-query-digest --type tcpdump --explain "h=localhost,u=root,p=xxxxx" --database dbname /tmp/mysql_pcap.txt

しかし別のところでまだエラーが。

# Tables
#    SHOW TABLE STATUS FROM `dbnamemysql_native_password` LIKE 'items'\G
#    SHOW CREATE TABLE `dbnamemysql_native_password`.`items`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT `items`.* FROM `items`  WHERE `items`.`id` = 847928\G
# EXPLAIN failed: DBD::mysql::db do failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 [for Statement "USE `dbname at /usr/bin/pt-query-digest line 7675.

database名にmysql_native_passwordとかってよくわからん文字列がくっついている。
tcpdumpを使うとかなんかの条件下でパースがうまくいってないのかな。

レポート処理のところで余計な文字列を削除してみる。(もっといい方法がありそう)

--- /usr/bin/pt-query-digest 2015-04-01 09:03:13.779851851 +0900
+++ /usr/bin/pt-query-digest    2015-04-03 08:30:11.688998565 +0900
@@ -6878,6 +6878,7 @@
          }
       }
 
+      $sample->{db} =~ s/\W.*$// if $sample->{db};
       $item_vals{default_db} = $sample->{db}       ? $sample->{db}
                               : $stats->{db}->{unq} ? keys %{$stats->{db}->{unq}}
                               :                       undef;

細かいことはよくわからんけど、とりあえずエラーは消えた。