Mysql之utf8和utf8mb4的区别
最近在项目中使用Mysql数据库保存emoji表情 😋 时报错
最近在项目中使用Mysql数据库保存emoji表情 😋 时报错
Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x8D' for column 'name'
坑了大半天,才知道Mysql的utf8编码并不是真正的UTF-8编码,Mysql的utf8最多只支持3个字节,而emoji表情、一些特殊的中文字符则需要4个字节才能存储, 因此才会报错。下面是来自维基百科的Unicode字符平面映射,其中UTF-8编码是U+2528D,属于CJK Unified Ideographs Extension B(中日韩统一表意文字扩充B)字符集的字符,处于第二辅助平面(SIP,表意文字补充平面),最多支持4个字节。而Mysql的utf8编码则属于常见的基本多文种平面(BMP,即Unicode编码范围在0000-FFFF之内)的字符,最多支持3个字节。
知道问题根源就好解决了,mysql在MySQL 5.6+版本之后支持4Bytes字节(utf8mb4)的存储,在官网上找到这么一段话。Mysql中的utf8mb4是对 原先utf8只能存储3个字节大小的字符的一种补充,是一种真正的UTF-8编码。
不多说,直接如下一顿操作,将数据库及表的字符集设置为utf8mb4,即可修复这个问题。
首先,将Mysql服务器的字符集设置为utf8mb4。通过命令 show variables like 'character%'; 可以查看数据库的字符集设置,下图是我已经配置好的截图。没配置之前,标红的两处变量character_set_database和character_set_server默认值都是latin1,必须都修改为 utf8mb4,否则其他修改后的字符集设置不会生效。
我这边是centos 7的云服务器, vim /etc/my.cnf 修改Mysql的配置文件,下面是正确的字符集配置
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
另外在建库时,需要指定字符集编码为 utf8mb4、字符集校对规则为 utf8mb4_general_ci 或 utf8mb4_unicode_ci(两者区别传送门)。
建表时也要指定 utf8mb4 编码,DDL语句如下所示:
CREATE TABLE IF NOT EXISTS pass_user(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(16) COMMENT '姓名',
age INT,
gender VARCHAR(8),
birthday BIGINT,
create_time BIGINT,
update_time BIGINT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
到这里还没完,因为mysql-connector-java驱动包在5.1.13+才支持utf8mb4,因此在选用连接驱动时需要注意驱动包的版本问题。
到此基本上问题已经得到解决,可以愉快的在Mysql数据库中插入4个字节的特殊字符了。如下是修改字符集之后的存储效果图,打完,收工!
https://dev.mysql.com/doc/refman/5.7/en/charset-unicode.html
作者:张小凡