mysql错误SQLstate[HY000];errorcode[1366];Incorrectstringvalue:'\xF0\xBF\xAA\xB7\xEF\xBF...'解决办法

今天在运行程序插入数据库时,出现了如下的bug:

org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [replace into task_result values(?,?,?,?)]; SQL state [HY000]; error code [1366]; Incorrect string value: '\xF0\xBF\xAA\xB7\xEF\xBF...' for column 'ip_info' at row 1; nested exception is java.sql.SQLException: Incorrect string value: '\xF0\xBF\xAA\xB7\xEF\xBF...' for column 'ip_info' at row 1。

网上百度了一下,是Emoji字符导致的。

虽然我修改了mysql的默认字符集为utf8,但是为3个字节,存储Emoji字符需要4个字节的utfm8。修改my.cnf。

修改前:

mysql错误SQLstate[HY000];errorcode[1366];Incorrectstringvalue:'\xF0\xBF\xAA\xB7\xEF\xBF...'解决办法_第1张图片

修改字符集:

mysql错误SQLstate[HY000];errorcode[1366];Incorrectstringvalue:'\xF0\xBF\xAA\xB7\xEF\xBF...'解决办法_第2张图片

修改后再次查看字符。

mysql错误SQLstate[HY000];errorcode[1366];Incorrectstringvalue:'\xF0\xBF\xAA\xB7\xEF\xBF...'解决办法_第3张图片

 

 

今天分享一个mysql数据插入异常的问题,由于工作排期问题,没有时间去深入研究这个问题,也因此困扰了我很久,问题大概是这样的,当我们把4个字节的字符插入到数据表列字符集为3个字节的表中时,会抛出以下异常,在没有异常捕获的情况下,导致程序崩溃以及事务持续性不健全

环境

mysql version: 5.6.35
JDK : 1.6.0_38

异常抛出:

nested exception is java.sql.SQLException: Incorrect string value: '\xF4\x80\x80\x8062...' for column 'ERROR' at row 1 
     at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83) 
     at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 
     at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 
     at org.springframework.orm.hibernate3.HibernateAccessor.convertJdbcAccessException(HibernateAccessor.java:424) 
     at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:410) 
     at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:424) 
     at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374) 
     at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:748) 
     at com.cargosmart.sime.core.persistence.dao.BaseDao.saveOrUpdate(BaseDao.java:39) 
     at ....
    Caused by: java.sql.SQLException: Incorrect string value: '\xF4\x80\x80\x8062...' for column 'ERROR' at row 1 
     at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073) 

问题分析:
我们可以看到上面异常中:Incorrect string value: '\xF4\x80\x80\x8062...' for column 'ERROR' at row 1,大致意思就是说对某数据库表列ERROR 插入了不正确的字符串值\xF4\x80\x80\x8062...,那到底为什么是错误的呢,首先我们可以看到那个不正确的字符串的特征,是一个4字节的十六进制的字符\xF4\x80\x80\x80,再查查表字符集发现为UTF-8,到这里还没发现根本问题,再仔细翻看了mysql官方version release notes,发现在version 5.5.3中发现有如下发布改进记录:

  • Changes in MySQL 5.5.3 (2010-03-24, Milestone 3)
Incompatible Change: The Unicode implementation has been extended to provide support for 
supplementary characters that lie outside the Basic Multilingual Plane (BMP). Noteworthy features:

utf16 and utf32 character sets have been added. These correspond to the UTF-16 and UTF-32 
encodings of the Unicode character set, and they both support supplementary characters.

The utf8mb4 character set has been added. This is similar to utf8, but its encoding allows up to 
four bytes per character to enable support for supplementary characters.

可以发现在version 5.5.3之后,增加了一种和utf-8类似的字符集utf8mb4,并且它的编码支持4个字节每个字符,再看看mysql的字符集所支持的字节范围:

mysql> SHOW CHARACTER SET;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
...
| utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |
...
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_general_ci  |      4 |
...

可以发现utf8最大支持3个字节的字符,到这里就基本确定是因为这个字符集设定所引起的异常,于是我试着修改对应列的字符集,这里的字符集分为表级字符集以及列级字符集,如果没有特别设定,列级字符集默认继承表级字符集,于是为了降低产品的影响面,我试着将发生异常的列的字符集改成utf8mb4,

ALTER TABLE ``.`` CHANGE COLUMN `ERROR` `ERROR` 
VARCHAR(500) CHARACTER SET 'utf8mb4' NULL DEFAULT NULL  ;

纠正:5.7往上版本

change改成modify

 

然后再重现了一下上面的异常,发现数据插入成功。至此,问题解决。

总结,这个异常的发生是由于4字节的字符插入到字符集为3字节的列中,在插入数据之前,字符集验证失败,字节溢出导致插入失败异常。
解决方法: 将对应列的字符集改成utf8mb4



作者:eason02
链接:https://www.jianshu.com/p/992bd01dbf60
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

 

 

你可能感兴趣的:(db)