ドライバって結構疑わしい挙動したりするので注意しましょう〜
久々のMySQLネタです。
今回はMySQL5.6で、datetime型のカラムへのinsertでエラーになる件についてです。
エラー内容
java側で生成した日付をdatetime型のカラムにinsertしようとすると、以下のエラーが発生しました。
Data truncation: Data too long for column
エラー発生環境
MySQLのバージョン
MySQL5.0 | エラーは起きない |
MySQL5.5 | エラーは起きない |
MySQL5.6 | エラーが起きる |
このように、MySQL5.6限定でエラーが発生します。
java側のコード
History history = new History(); history.date = new Timestamp(new Date().getTime()); historyService.insert(history);
こんな感じに日付を設定しています。至って普通のコードです。
ここで設定される日付の値は以下の通りです。
2014-06-11 20:27:28.142
s2jdbcを使っていますが、s2jdbcに限らず発生するでしょう。
SQLモード
mysql> show variables like 'sql_mode'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | sql_mode | | +---------------+-------+
strictモードではないので、Data too long for columnは発生せず、warnが起きつつデータ末尾が切り捨てられてinsertされるはずです。
しかし、MySQL5.6だけData too long for columnが発生します。
SQLのログ
MySQL5.6でエラーが発生する時のgeneral.logには以下のように記録されていました。
48 Prepare insert into HISTORY (DATE) values (?) 48 Query rollback
さて、このログを見てお気づきでしょうか?
Prepareの後にExecuteが無いだと!?
通常 Prepare → Execute → rollback 、という順に処理がされるはずです。
しかしこのログを見るとSQLが実行すらされていない事が分かります。
犯人は・・・・
ずばり、
JDBCドライバーが犯人
でした。
具体的には、以下のような動作の違いがありました。
ドライバのバージョン | MySQL5.0 | MySQL5.5 | MySQL5.6 |
---|---|---|---|
mysql-connector-java-5.0.3-bin.jar | エラーは起きない | エラーは起きない | エラーは起きる |
mysql-connector-java-5.1.31-bin.jar | エラーは起きない | エラーは起きない | エラーは起きない |
勘弁して下さいよJDBCドライバさん
雑感
general.logを見た時、MySQLまで処理が届く前にエラーが返されている、つまりJDBCドライバが何かしてやがるな?と思ったらビンゴでした。
こういう謎のエラー系は落ち着いてエラーが起きるタイミングを見極めると解決が早くなりますね。
あれ?でも半年前からこのエラーが起きて解決できないって言ってたよね
ちょっと黙ってて