前言
之前一直认为UTF-8是万能的字符集问题解决方案,直到最近遇到这个问题。最近在做新浪微博的爬虫, 在存库的时候发现只要保持emoji表情,就回抛出以下异常:
Incorrect string value: '\xF0\x90\x8D\x83\xF0\x90...'
众所周知UTF-8是3个字节, 其中已经包括我们日常能见过的绝大多数字体. 但3个字节远远不够容纳所有的文字, 所以便有了utf8mb4, utf8mb4是utf8的超集, 占4个字节, 向下兼容utf8. 我们日常用的emoji表情就是4个字节了.
所以在此我们像utf8的数据表插入数据就会报出Incorrect string value这个错误.
Google一下很容易就找到了解决方案, 具体解决办法是如下:
一、修改数据表的字符集为utf8mb4
这点很简单, 修改语句网上找一大堆, 不过建议重新建表, 使用 mysqldump -uusername -ppassword database_name table_name > table.sql 备份相应数据表, 并修改其中的建表语句的字符集为 utf8mb4 即可, 然后 mysql -uusername -ppassword database_name < table.sql 重新导入sql即可完成修改字符集操作.
二、MySQL数据库版本要5.5.3及以上
网络上所有的文章都说明要MySQL 5.5.3以上的版本才支持utf8mb4, 不过我使用的数据库版本为5.5.18, 最终仍能解决问题, 所以同学们不要急着找运维哥哥升级数据库先, 先试试能不能自己解决问题.
三、修改数据库配置文件/etc/my.cnf并重启mysql服务
主要是修改数据库的默认字符集, 以及连接, 查询的字符集, [Mysql支持emoji 表情符号 升级编码为UTF8MB4][1] 这篇文章有详细的设置方法, [深入Mysql字符集设置][2] 这篇文章有其中设置的各个字符集的作用, 大家可以科普下.
四、升级MySQL Connector到5.1.21及以上
以上所有的操作, 最关键的是步骤3, 修改数据库的配置文件, 其中大概修改了
[client] # 客户端来源数据的默认字符集 default-character-set = utf8mb4 [mysqld] # 服务端默认字符集 character-set-server=utf8mb4 # 连接层默认字符集 collation-server=utf8mb4_unicode_ci [mysql] # 数据库默认字符集 default-character-set = utf8mb4
这些配置指定了数据从客户端到服务端所经过的一条条管道使用的字符集, 其中每一个管道出现问题都可能会导致插入失败或者乱码.
但很多时候, 线上的数据库是不能随便修改数据库文件的, 所以我们的运维同学很果断的回绝了我修改数据库配置文件的请求(T_T)
所以就只能用代码解决了, 一开始是准备从JDBC连接时候就指定使用的字符集处下手.
jdbc:mysql://localhost:3306/ding?characterEncoding=UTF-8
主要把UTF-8修改为utf8mb4对于的Java Style Charset字符串应该就能解决问题吧?
不过很遗憾的是, Java JDBC并不存在utf8mb4对于的字符集. 使用UTF-8的时候可以兼容urf8mb4并自动转换字符集.
For example, to use 4-byte UTF-8 character sets with Connector/J, configure the MySQL server with character_set_server=utf8mb4, and leave characterEncoding out of the Connector/J connection string. Connector/J will then autodetect the UTF-8 setting. – [MySQL:Using Character Sets and Unicode][3]
后来科普了一下, 在每一次查询请求的时候, 可以显式的指定使用的字符集, 使用 set names utf8mb4 可以指定本次链接的字符集为utf8mb4, 但这个设置在每次连接被释放后都会失效.
目前的解决办法是, 在需要插入utf8mb4的时候, 显示地调用执行set names utf8mb4, 如:
jdbcTemplate.execute("set names utf8mb4"); jdbcTempalte.execute("...");
需要注意的是, 我们在使用一下ORM框架的时候, 因为性能优化原因, 框架会延迟提交, 除非事务结束或者用户主动调用强制提交, 负责执行的set names utf8mb4仍然不会生效.
在这里我使用的是myBatis, 以MessageDao为例
// MessageDao public interface MessageDao { @Update("set names utf8mb4") public void setCharsetToUtf8mb4(); @Insert("insert into tb_message ......") public void insert(Message msg); } // test code SqlSession sqlSession = sqlSessioFactory.openSession(); messageDao = sqlSession.getMapper(MessageDao.class); messageDao.setCharsetToUtf8mb4(); // 强制提交 sqlSession.commit(); messageDao.insert(message);
至此, 问题便解决了..
哎, 如果世事能那么顺利就好了, 在项目中, mybatis是实例是交由Spring去管理的, 也就是说我拿不到sqlSession, 也就是强制提交不了. 并且因为Spring事务框架的限制, 他并不允许用户显式调用强制提交. 目前还在纠结这个问题.
有两个解决思路:
总结
以上就是这篇文章的全部内容了,待有时间再实验一下以上两种方案。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持。
本文向大家介绍mysql中插入emoji表情失败的原因与解决,包括了mysql中插入emoji表情失败的原因与解决的使用技巧和注意事项,需要的朋友参考一下 失败场景 用户昵称中存在emoji表情,调用jdbc往mysql数据库插入的时候抛出异常 java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\x9B' 失败原因 mysql的
在hackerearth下面的qn已经被问到了编码qns中的一个 离零最远 给出了一个大小为N的整数数组A。 任务编写一个程序来打印从0到最远的元素。如果有多个元素,则打印值最小的数字。 输入格式 第一行包含一个整数N,表示数组a的大小。 下一行包含N个整数,表示数组A的元素。 输出格式 1 2 3 4 5 样本输出1 5 我准备的解决方案: 问:这个解决方案对于最初的场景对我有效,但是当我提交它
本文向大家介绍MySQL批量插入和唯一索引问题的解决方法,包括了MySQL批量插入和唯一索引问题的解决方法的使用技巧和注意事项,需要的朋友参考一下 MySQL批量插入问题 在开发项目时,因为有一些旧系统的基础数据需要提前导入,所以我在导入时做了批量导入操作 ,但是因为MySQL中的一次可接受的SQL语句大小受限制所以我每次批量虽然只有500条,但依然无法插入,这个时候代码报错如下: nested
本文向大家介绍java处理数据库不支持的emoji表情符问题解决,包括了java处理数据库不支持的emoji表情符问题解决的使用技巧和注意事项,需要的朋友参考一下 一般数据库的编码是utf8,utf8是不支持存储表情符的,当存入的微信昵称带有表情符时就会出现乱码情况,有两种解决方法: 1.mysql数据库升级到5.5版本以上,utf8改为utf8mb4,utf8mb4的字符最多可以是4个字节,可以
我在一个Spray应用程序中使用ask模式调用一个Actor,并将结果作为HTTP响应返回。我将故障从参与者映射到自定义错误代码。 当authActor发送一个失败时,这可以正常工作,但是如果authActor抛出一个异常,则在请求超时完成之前什么也不会发生。例如: 这样,如果它是预期的错误(即ServiceException),则通过创建一个失败来处理它。如果它是意外的,它会立即返回一个失败,以
本文向大家介绍关于python pyqt5安装失败问题的解决方法,包括了关于python pyqt5安装失败问题的解决方法的使用技巧和注意事项,需要的朋友参考一下 前言 最近在工作中遇到一个问题,python pyqt5在安装的时候居然提示失败了,无奈只能找解决的办法,发现网上有同样遇到这个问题的同学,所以就总结了解决的方法分享出来,下面话不多说了,来一起看看详细的介绍: 发现问题 以前装命令都是