2016年10月9日日曜日

古いpiwikとMySQL5.6

わけありでアップデートができないpiwik2.1のDBを、MySQL5.6に引き上げました。

しかし、エラー発生。

「MySQL gone away」
mysqlがどっかいっちゃったよ~というエラーです。
コネクションが意図しないタイミングで閉じられた場合に発生するエラーです。

エラータイミングは、piwikのアーカイブ生成時でした。

設定が悪いのか、ログファイルに詳細なエラー内容は無しの状態。

ぐぐると、タイムアウトとか、バッファが足りないからというのしかなく、解決になりませんでした。

そこで!
sqlを実行させるさせる所でバックトレース内容を出力させて調査。
gone awayエラーが発生したクエリ実行時のバックトレースを追っていきました。

gone awayが発生したクエリでは、その時点ではすでに接続がきれているので、もっと手前で本当のエラーが発生しているだろうと当たりをつけます。
エラーで完了できず、次のクエリで gone awayかなと。

手前のクエリのバックトレースと比較して、最後の共通メソッド・・・すなわちメインロジックを探します。
そこの例外内容を確認すると・・・あった!
csvファイルでテーブルに書き込んでいるところで、値がutf8じゃないよエラーをPDOがスローしていました。


クエリ実行メソッドを見ると、クエリを実行するたびに接続のチェックをしているみたいだけど、これがどうもすり抜けている状態です。
csvでの取り込みにしっぱいしたら、エラーをもみ消して通常のクエリで挿入というロジックもどうなのかと。


まとめると
csv取り込みエラーで接続消滅。 utf8でデータ挿入するも、blobカラムの値がバイナリデータとなっていた。
ここのエラーで接続が切れる。
しかし、シングルトンの変数の中身が null とならないため、接続中と判定される。
そのまま接続オブジェクトを使いまわそうとして、gone away。 もう接続切れてるからね!

今までは、接続中と判定されず、再接続ができていたのでしょうか。
それとも文字判定が無かったのでしょうか。

解決編

解決すには、バイナリデータを16進数にするか、挿入時の文字コードをlatin1にするか、csvによる挿入をコメントアウトするか。

csv挿入は、1つのクエリで一気に挿入できるのでパフォーマンがいい。このままにしたい。
16進数にするには、文字列として扱われないように改造が必要になりそう。嫌だ。
残る強制latin1、テーブルを見るとマルチバイトが入るカラム無し。 これに決めた!

core/Db/BatchInsert.php::tableInsertBatch()
csv定義配列に、'charset' => 'latin1' を追加するのみ。