文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

MySQL5.6のData truncation: Data too long for columnとJDBCドライバの罠

ドライバって結構疑わしい挙動したりするので注意しましょう〜


f:id:treeapps:20180418131549p:plain

久々の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ドライバが何かしてやがるな?と思ったらビンゴでした。


こういう謎のエラー系は落ち着いてエラーが起きるタイミングを見極めると解決が早くなりますね。


あれ?でも半年前からこのエラーが起きて解決できないって言ってたよね


ちょっと黙ってて