mysql中错误码1406 data too long在jdbc和命令行的不同表现及处理

今天在同事开发过程中碰到一个mysql的错误码:1406,显示的错误信息为 data too long for column,而导致相应的事务被回滚.将此错误码(google 关键字 mysql 1406),即搜索到相应的错误信息,即相应的插入数据比实际的列的大小更大.然后,报相应的错误信息,最终处理失败.

但是,对于这条sql语句,如果将语句贴到命令行去执行,即得到另外一个结果.sql不会报错,但再次查询相应的数据信息,会发现插入的数据被自动截断了.在这种情况下,实际上插入的数据是错误的,即因为不同的行为得到不同的结果.

然后,再次google(关键字 mysql自动截断)会发现这两种情况是因为使用了不同的sql_mode导致.获取相应的sql_mode命令可以如下所示(笔者mysql为mariadb 10.1)

select @@sql_mode;

获取的数据信息为:NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION.

这种情况下,即会产生自动截断的设置.可以通过set @@sql_mode="xxx"来修改.影响截断地设置为 strict_trans_tables 或者 strict_all_tables.将其设置为其中之一即可.

反之,使用默认的jdbc连接mysql时,同样通过命令获取相应的数据,结果为
NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
会发现相应的设置并不与命令行相同.

这里的原因在于,在mysql的jdbc驱动中,之前也是与命令行相同,但为了保证与jdbc规范相符(具体的规范没找到),引入了配置变量 jdbcCompliantTruncation.此变量可以在连接字符串中,追加并设置为false.其默认值为true.
在具体的mysql jdbc实现中(当前版本为5.1.39),此变量会在类ConnectionImpl中判定.如果为true,并且版本大于5.0.2,则会发语句set sql_mode=xxx 来进行重新设置.其重新设置的值,即在之前提到值的基础之上,追加值 STRICT_TRANS_TABLES. 然后,在此设置的影响下,插入数据超长即会直接报错,而不是自动截断.

另外,如果想在mysql服务器中修改此值,则可以在my.conf中通过以下修改来达到目的:

sql_mode=NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

在google中,我们还可以看到另外一个设置,即strict_all_tables,两者都可以达到相同的目的,两者的区别在于在处理非事务数据库引擎如myiasm中,其工作不一样.strict_trans_tables会在插入多条数据时(如果第1条为正确的),后续错误数据myiasm表中自动截断,而strict_all_tables会报错.但两者都会插入已经成功的数据.即看起来,strict_trans_table会插入错误的数据,而strict_all_tables会插入部分数据,两个看起来都很有问题.
参考文章:http://www.noelherrick.com/blog/mysql-strict_all_tables-vs-strict_trans_tables

转载请标明出处:i flym
本文地址:https://www.iflym.com/index.php/code/201607040001-2.html

相关文章:

作者: flym

I am flym,the master of the site:)

发表评论

邮箱地址不会被公开。 必填项已用*标注