第12回、
今回は、
エラーに関するクライアント間の差異
MySQLから見た場合、
MySQLのエラーコードは4桁の数字ですが、ER_
というマクロが定義されており、libmysqlclient.
がこれにあたります)
JavaのクライアントライブラリであるConnector/ER_
はSQL_
にマッピングされています。Connector/SQL_
には"Data source rejected establishment of connection"というエラーメッセージが紐づけられています。
このように、
クライアントがMySQLから受け取る情報
リファレンスマニュアルのサーバのエラーコードおよびメッセージにも記載がありますが、
エラーコードは
$ mysql -h127.0.0.1 -P64058 -uroot -p Enter password: ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1' (111) $ mysql -h127.0.0.1 -P64057 -uroot -p Enter password: ERROR 1130 (HY000): Host '127.0.0.1' is not allowed to connect to this MySQL server $ mysql -hlocalhost -S/usr/mysql/5.7.11/data/mysql.sock -uroot -p Enter password: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
最初のコマンドは、2003
番が返却されています。クライアントサイドなのでSQLSTATEは存在せず、HY000
が入っています。続く文字列はエラーメッセージですが、1130
番が返却されています。3番目も同様に、1045
番、28000
が入りました。
このように、mysql
コマンドラインクライアントからMySQLサーバに接続できない」
全くの余談ですが、/etc/
などの設定ファイルにlc_
と追加することで以下の例のように日本語にすることはできますが、en_
のままでエラーメッセージを英語で出力するため、
$ mysql -hlocalhost -S/usr/mysql/5.7.11/data/mysql.sock -uroot -p Enter password: ERROR 1045 (28000): ユーザー 'root'@'localhost' のアクセスは拒否されました。(using password: YES)
MySQLからのエラーをモニタリングする
最初の段落でも少し触れましたが、
これはヘルスチェック用のスクリプトと比べて、
- 1.影響の大小を判定しやすい
たとえば、
ある特定のレコードが長期間ロックされたままになっている事態を想定します。その特定のレコードがアプリケーションの動作に不可欠なレコードだった場合、 たった1行の長期間のロックはアプリケーションに多大な影響を与えます (そして、 大量のエラーがアプリケーションに返るでしょう)。逆に、 1ヵ月に1回しか必要とされないレコードであれば、 実際に利用するタイミングまではロックが続いていてもそれほど問題になることはないでしょう (エラーログは出ても散発的になります)。これらはMySQL (および、 MySQLを全体的に監視するスクリプト) からすれば、 飽くまで 「あるテーブルのある行が長時間ロックされていた」 というだけであり、 それがどの程度の影響かを測るのは困難です。 - 2.どこに問題があるかの絞り込みまでは期待できない
エラー番号
2006
番のCR_
は、SERVER_ GONE_ ERROR コネクションがMySQLサーバから一方的に切断された場合にクライアントライブラリ (Connector/ Cの場合。他のクライアントライブラリの場合は異なります) が出力するエラーコードです (エラー番号の2000番台はクライアント用に予約されていますので、 MySQLサーバから2000番台のエラーが返却されることはありません)。アプリケーションから見れば、 それがサーバでエラーになったのかクライアントライブラリの中でエラーになったのかは特に判定されず、 「クエリーを実行しようとしたところエラーになった」 という情報が渡されます。サーバ側のエラーなのかクライアント側のエラーなのかは、 例外機構の中でエラーコードを見て判定することになるでしょう (あるいは、 それは判別する必要はないかも知れません)。 -
このエラーコードの原因になり得る原因をMySQLサーバ側から探すと、
このエラーをクライアントライブラリが発し得るのは、 「 KILL
ステートメントを利用して人為的にコネクションを切断した」場合や 「アイドルタイムアウト ( wait_
またはtimeout interactive_
)timeout によりコネクションが切断された」 場合、 「MySQLサーバがダウンし、 コネクションが破棄されてしまった」 場合などが考えられます。またサーバ側にもクライアント側にも問題がなかったとしても、 中間のネットワークやNICの状態の変化、 ファイアウォールの設定変更など、 原因になり得る事象はいくつも存在します。これらはエラーメッセージからだけでは原因は追究できません。 - 3.記録として残しやすい
MySQLサーバにとってはエラーの返却は
「エラーになるべき処理を中断し、 エラーコードを返却した」 という正常な動作です (たとえば、 存在しないテーブルに対する INSERT
ステートメントがそのようにエラー処理されないのであれば、それこそがMySQLサーバにとっての異常 (=バグ) です)。基本的にMySQLのエラーログにはクライアントに返却したエラーコードやその詳細は記録されませんので、 クライアント側でログを残すことになります。昨今、 アプリケーションの動作ログはユーザーの行動情報などを抽出するために保管される機会が増えていますので、 MySQLのエラーも併せて (同じログファイルである必要はありませんが) 記録しておくことで、 MySQLで問題が発生したタイミングとユーザー動向の相関や周期性などを発見しやすくすることができます。
サーバサイドの死活監視とクライアントサイドでのエラーハンドリングを併せて上手く監視することで、