MySQL字符集设置,utf8和utf8mb4区别
前言
做网站开发的同学肯定都遇到过中文乱码的问题。本来好好的中文,存到数据库里就变成问号或者乱码了。这其实很大概率就是字符集设置不对导致的。
很多新手同学不知道utf8和utf8mb4有什么区别,建库的时候直接用默认的utf8,结果存个emoji表情就报错了,或者存进去之后变成乱码。
这篇文章就详细讲讲MySQL字符集的设置方法,以及utf8和utf8mb4到底有什么区别,应该怎么选。
一、utf8和utf8mb4的区别
首先大家要搞清楚一个坑:MySQL里的utf8并不是真正的UTF-8。
MySQL里的utf8字符集,每个字符最多只能存3个字节。而真正的UTF-8编码,有些字符是占4个字节的,比如emoji表情(😀😂👍这些),还有一些生僻字。
所以如果你用utf8字符集,存emoji表情的时候就会报错,或者存进去之后变成乱码。
而utf8mb4才是真正的UTF-8,每个字符最多可以存4个字节,emoji表情、生僻字都能正常存。
总结一下:
- utf8:每个字符最多3字节,存不了emoji表情
- utf8mb4:每个字符最多4字节,完全兼容UTF-8,推荐使用
现在做新项目,直接用utf8mb4就对了,不要再用utf8了。
二、查看当前MySQL字符集设置
先看看你的MySQL现在用的是什么字符集:
SHOW VARIABLES LIKE '%character%';
执行完之后会看到类似下面的输出:
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
重点看这几个:
- character_set_server:服务器默认字符集
- character_set_database:当前数据库的字符集
- character_set_client:客户端字符集
- character_set_connection:连接字符集
- character_set_results:查询结果字符集
最好这几个都统一成utf8mb4,这样就不会有乱码问题了。
三、新建数据库的时候指定utf8mb4
如果你要新建一个数据库,直接在建库的时候指定字符集:
CREATE DATABASE testdb
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
这样建出来的数据库默认就是utf8mb4字符集了。
新建表的时候也可以指定:
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
四、修改MySQL默认字符集
如果你想把MySQL的默认字符集改成utf8mb4,可以修改my.cnf配置文件。
找到MySQL的配置文件 /etc/my.cnf,在 [mysqld] 下面添加:
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
修改完之后重启MySQL服务:
systemctl restart mysqld
这样以后新建的数据库和表就默认都是utf8mb4字符集了。
五、修改已有数据库的字符集
如果你的数据库已经建好了,想改成utf8mb4,可以执行:
ALTER DATABASE testdb
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
注意:这个只会修改数据库的默认字符集,已经建好的表的字符集不会变。
六、修改已有表的字符集
如果要修改某一张表的字符集,可以执行:
ALTER TABLE users
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
这样整张表的所有字段都会改成utf8mb4字符集。
如果要批量修改整个数据库里所有表的字符集,可以生成一个SQL脚本:
SELECT CONCAT('ALTER TABLE ', table_name, ' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;')
FROM information_schema.tables
WHERE table_schema = 'testdb';
执行完之后会生成一堆ALTER TABLE语句,把这些语句复制出来执行就行。
七、连接的时候指定字符集
除了数据库和表的字符集,连接的时候也要指定字符集,不然还是可能会乱码。
用命令行连接的时候:
mysql -u root -p --default-character-set=utf8mb4
或者登录之后执行:
SET NAMES utf8mb4;
常见坑
坑1:用了utf8字符集,存emoji表情报错
很多同学建库的时候用的是utf8,结果存个emoji表情就报错了,或者存进去之后变成问号。这就是因为utf8最多只能存3个字节,emoji表情是4个字节的。
解决方法就是把字符集改成utf8mb4。
坑2:数据库字符集改了,但是表的字符集没改
很多同学改完数据库的字符集之后,以为就完事了,结果还是乱码。这是因为数据库的默认字符集改了,但是已经建好的表的字符集还是旧的。
一定要把表的字符集也一起改了,最好是整张表转成utf8mb4。
坑3:连接字符集不对,导致中文乱码
有时候数据库和表都是utf8mb4,但是查出来还是乱码。这一般是连接字符集不对。可以执行 SET NAMES utf8mb4 试一下,或者连接的时候加上 --default-character-set=utf8mb4 参数。
坑4:utf8mb4_general_ci和utf8mb4_unicode_ci选哪个
很多同学不知道这两个排序规则有什么区别。简单来说:
- utf8mb4_general_ci:速度快,但是对一些特殊字符的排序可能不太准确
- utf8mb4_unicode_ci:排序更准确,但是速度稍微慢一点
一般网站用utf8mb4_general_ci就够了,不用太纠结。
总结
MySQL字符集和utf8mb4的核心知识点:
- MySQL的utf8不是真正的UTF-8,最多只能存3字节
- utf8mb4才是真正的UTF-8,能存emoji表情,推荐使用
- 新建数据库和表的时候直接用utf8mb4
- 老的数据库如果要改,要同时改数据库和表的字符集
- 连接的时候也要指定utf8mb4,不然还是会乱码
现在做新项目,直接全程用utf8mb4就对了,省得以后再改。
遇到问题加QQ23979811 协助处理