前端:Java
客户端:IOS
数据库:PerconaServer5.5.20
JDBCURL:jdbc:mysql://192.168.1.1:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE
表结构:| groupname | varchar(32) | utf8mb4_general_ci
utf8-mb4字符集是MySQL 5.5新增的,我们的业务使用该字符集字段存放图片,比如:手机客户端发出的表情,相比传统字符集和二进制存储方式相比,mb4空间占用小,响应速度快。
手册介绍mb4是定义到列的,可是在实际的应用中是无效的。我们测试了三个场景,分别来验证这个问题。
场景一:character_set_server=utf8 重启mysqld
mysql> show variables like '%character%'; +--------------------------+-------------------------------------------+ | Variable_name | Value | +--------------------------+-------------------------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /data/mysqlPerconasvr5520/share/charsets/ | +--------------------------+-------------------------------------------+8 rows in set (0.00 sec)
客户端插入数据,程序报错!
查看数据库,数据未插入表中!
根据场景一的问题,我们首先修改了JDBCURL,将characterEncoding=utf8修改为characterEncoding=utf8mb4后又出现了新的问题,MySQL官方驱动目前不支持utf8mb4。
网上有的同学修改了驱动源码, if(str=utf8mb4) str=utf8 ,总的来说也是治标不治本,只是将utf8mb4重定向到utf8上了而已,满足可以在JDBCURL中指定,但实际的字符集还是走的utf8。这不是我们想要的。于是我们修改了MySQL配置。
场景二:character_set_server=utf8mb4 重启mysqld
mysql> show variables like '%character%';
+--------------------------+-------------------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /data/mysqlPerconasvr5520/share/charsets/ |
+--------------------------+-------------------------------------------+
8 rows in set (0.00 sec)
数据插入成功!
客户端反馈正常!
总结:目前MySQL最新的官方驱动是不支持utf8mb4字符集的,所以我们的解决方法就是采用的场景二的配置,给我们DBA带来的问题就是需要将使用到utf8mb4字符集的表迁移到一个新的实例中,因为场景二的配置需要重启mysqld,我们又不希望停止MySQL服务。
友情提示:如果你想在线修改字符集来满足需求,这就是我们的场景三,就不在此展示了,因为从数据库状态看,字符集修改是成功的,插入数据是失败的。
----
正确的做法是:
1.修改表的字符集为utf8mb4;
2.在线set golbal character_set_database=utf8mb4;
3.断开与实例的连接((DBA测试也要断开一次连接,重新登录mysql)
4.jdbc url去掉字符集项,连接到mysql实例后,会使用database的字符集