我们的一些业务系统最近出现了一种情况,尤其是新版的ios 设备,在发布消息时,使用了表情符号时,
对gbk 字符集的数据库,写入数据库的数据,在回显时,变成 ‘口口’ 无法回显,
对utf8 字符集的数据库,则根本无法写入数据库,客户端程序直接报 java.io.exception xxxxxxxx.
原因在哪里呢?
各种移动设备,各种不同的输入法,都会自带一些增强版的‘bmp‘ 表情符号。
这些表情符号编码为 4个字节的 字符, utf8 字符集目前只支持1-3 个字节的字符,导致数据无法入库。
解决方案 有两种:
1. 遍历输入的文本,把四字节长度的字符,修正为自定义的字符替换掉,有一定的工作量。
2. 修改数据库字符集, 把数据库字符集从utf8 修改为支持1-4 个字节字符的utf8mb4
mysql 从 5.5.3 版本开始支持 utf8mb4 字符集 , 从 mysql 5.5.3 之后版本基本可以无缝升级到 utf8mb4 字符集。
3.升级方案:
1) 修改数据库字符集character-set-server=utf8mb4 重启数据库生效。
[mysqld]
character-set-server=utf8mb4
2) 修改database 的字符集为 utf8mb4
alter database dbname character set=utf8mb4
3) 修改表的字符集 为utf8mb4
alter table tablename character set = utf8mb4
4. 需要注意的一些点。
1) innodb 索引只能支持 767 的字节,对utf8 大约可以为255 字符做索引, 对utf8mb4 就只有 191 个字符了,你的索引可能要重新定义。
2) 你的char varchar 的字段定义可能要重新定义或者修改为 text 类型。
3) utf8mb4 是utf8 的一个超集, utf8 字符的编码,位置, 存储 在utf8mb4 与utf8 字符集里一样的,不会对有现有数据带来损坏。
4) 谨慎起见,请详细测试你的应用对该字符集的兼容性问题。
字符集设置:
mysql> SHOW VARIABLES WHERE Variable_name LIKE ‘character\_set\_%‘ OR Variable_name LIKE ‘collation%‘; +--------------------------+-----------------+ | 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 | | collation_connection | utf8_general_ci | | collation_database | utf8_general_ci | | collation_server | utf8_general_ci | +--------------------------+-----------------+ 10 rows in set (0.20 sec)
mysql> SET character_set_client = gbk; Query OK, 0 rows affected (0.31 sec) mysql> SET character_set_connection=gbk ; Query OK, 0 rows affected (0.00 sec) mysql> set character_set_database=utf8mb4; Query OK, 0 rows affected (0.00 sec) mysql> set character_set_filesystem=binary; Query OK, 0 rows affected (0.00 sec) mysql> set character_set_results=gbk; Query OK, 0 rows affected (0.00 sec)
mysql> set character_set_system=utf8;
ERROR 1238 (HY000): Variable ‘character_set_system‘ is a read only variable
mysql> set names gbk; 它相当于下面的三句指令: SET character_set_client = gbk; SET character_set_results = gbk; SET character_set_connection = gbk;
SET NAMES ‘charset_name
‘ COLLATE ‘collation_name
‘
[client] //通过连接器连接 EG:PHP [mysql] //mysql程序登陆时的字符集
default-character-set = gbk
//等价
--SET character_set_client = gbk;
--SET character_set_results = gbk;
--SET character_set_connection = gbk;
#character_set_system=utf8mb4 #character_set_client=utf8mb4 #character_set_connection=utf8mb4 #character_set_database=utf8mb4 #character_set_results=utf8mb4 // #代表相应变量不能设置在这个区中,报错,mysql登陆报错
[mysqld] //mysqld起动时设置字符集
character_set_filesystem=binarycharacter-set-server=utf8mb4
collation-server = utf8mb4_unicode_ciinit_connect=‘set autocommit=0; set names gbk;‘ //root 用户不会执行
#character_set_system=utf8mb4#character_set_client=utf8mb4 #character_set_connection=utf8mb4 //#代表相应变量不能设置在这个区中,mysqld 起动报错#character_set_database=utf8mb4 #character_set_results=utf8mb4 []
mysql> select * from t1; +------------+-----------------+---------------------+ | cur_user | n_user | in_time | +------------+-----------------+---------------------+ | @localhost | mysql@localhost | 2016-07-05 00:25:02 | +------------+-----------------+---------------------+ 1 row in set (0.19 sec) mysql> ALTER TABLE t1 MODIFY cur_user CHAR(50) CHARACTER SET sjis; mysql> show create table t1; CREATE TABLE `t1` ( `cur_user` char(50) CHARACTER SET sjis DEFAULT NULL, `n_user` varchar(100) CHARACTER SET utf8 DEFAULT NULL, `in_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4