在MySQL 8.0版本之前,默认字符集为
latin1
,utf8字符集指向的是utf8mb3
。网站开发人员在数据库设计的时候往往会将编码修改为utf8字符集。如果遗忘修改默认的编码,就会出现乱码的问题。从MySQL 8.0开始,数据库的默认编码将改为utf8mb4
,从而避免上述乱码的问题
1、查看默认使用的字符集
SHOW VARIABLES LIKE 'character%';
或
SHOW VARIABLES LIKE '%char%';
image.png
- MySQL 5.7 默认的客户端和服务器都用了
latin1
,不支持中文,保存中文会报错 image.png
2、修改字符集
- 编辑
my.cnf
vim /etc/my.cnf
- 配置支持中文字符集
character_set_server=utf8
- 重新启动MySQL服务
systemctl restart mysqld
- 修改已创建数据库的字符集
alter database dbtest1 character set 'utf8';
- 修改已创建数据表的字符集
alter table t_emp convert to character set 'utf8';
3、各级别的字符集
服务器级别
数据库级别
表级别
列级别
- 查看系统字符集
show variables like 'character%';
或
SHOW VARIABLES LIKE '%char%';
image.png
- character_set_server:服务器级别的字符集
- character_set_database:当前数据库的字符集
- character_set_client:服务器解码请求时使用的字符集
- character_set_connection:服务器处理请求时会把请求字符串从character_set_client转为
- character_set_connection character_set_results:服务器向客户端返回数据时使用的字符集
1. 服务器级别
-
character_set_server
:服务器级别的字符集
我们可以在启动服务器程序时通过启动选项或者在服务器程序运行过程中使用 SET 语句修改这两个变量的值。比如我们可以在配置文件中这样写
[server]
character_set_server=gbk # 默认字符集
collation_server=gbk_chinese_ci #对应的默认的比较规则
- 当服务器启动的时候读取这个配置文件后这两个系统变量的值便修改了
2. 数据库级别
-
character_set_database
:当前数据库的字符集
们在创建和修改数据库的时候可以指定该数据库的字符集和比较规则
CREATE DATABASE 数据库名 [[DEFAULT] CHARACTER SET 字符集名称] [[DEFAULT] COLLATE 比较规则名称];
ALTER DATABASE 数据库名 [[DEFAULT] CHARACTER SET 字符集名称] [[DEFAULT] COLLATE 比较规则名称];
3. 表级别
我们也可以在创建和修改表的时候指定表的字符集和比较规则
CREATE TABLE 表名 (列的信息) [[DEFAULT] CHARACTER SET 字符集名称] [COLLATE 比较规则名称]]
ALTER TABLE 表名 [[DEFAULT] CHARACTER SET 字符集名称] [COLLATE 比较规则名称]
- 如果创建和修改表的语句中没有指明字符集和比较规则,将使用该表所在数据库的字符集和比较规则作
为该表的字符集和比较规则
4. 列级别
对于存储字符串的列,同一个表中的不同的列也可以有不同的字符集和比较规则。我们在创建和修改列
定义的时候可以指定该列的字符集和比较规则
CREATE TABLE 表名
(
列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称], 其他列
...
);
ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];
- 对于某个列来说,如果在创建和修改的语句中没有指明字符集和比较规则,将使用该列所在表的字符集
和比较规则作为该列的字符集和比较规则
4. 小结
- 如果
创建或修改列
时没有显式的指定字符集和比较规则,则该列默认用表
的字符集和比较规则 - 如果
创建表时
没有显式的指定字符集和比较规则,则该表默认用数据库
的字符集和比较规则 - 如果
创建数据库时
没有显式的指定字符集和比较规则,则该数据库默认用服务器
的字符集和比较规
则
5.字符集与比较规则
1. utf8 与 utf8mb4
-
utf8
字符集表示一个字符需要使用1~4个字节,但是我们常用的一些字符使用1~3个字节就可以表示了。而字符集表示一个字符所用的最大字节长度,在某些方面会影响系统的存储和性能,所以设计MySQL的设计者偷偷的定义了两个概念-
utf8mb3
:阉割过的utf8
字符集,只使用1~3个字节表示字符 -
utf8mb4
:正宗的utf8
字符集,使用1~4个字节表示字符
-
2. 比较规则
image.pngMySQL版本一共支持41种字符集,其中的 Default collation 列表示这种字符集中一种默认的比较规则,里面包含着该比较规则主要作用于哪种语言,比如 utf8_polish_ci 表示以波兰语的规则比较, utf8_spanish_ci 是以西班牙语的规则比较, utf8_general_ci 是一种通用的比较规则。后缀表示该比较规则是否区分语言中的重音、大小写
- 常用操作1
#查看GBK字符集的比较规则
SHOW COLLATION LIKE 'gbk%';
#查看UTF-8字符集的比较规则
SHOW COLLATION LIKE 'utf8%';
- 常用操作2
#查看服务器的字符集和比较规则
SHOW VARIABLES LIKE '%_server';
#查看数据库的字符集和比较规则
SHOW VARIABLES LIKE '%_database';
#查看具体数据库的字符集
SHOW CREATE DATABASE dbtest1;
#修改具体数据库的字符集
ALTER DATABASE dbtest1 DEFAULT CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
- 常用操作3
#查看表的字符集
show create table employees;
#查看表的比较规则
show table status from atguigudb like 'employees';
#修改表的字符集和比较规则
ALTER TABLE emp1 DEFAULT CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
3.请求到响应过程中字符集的变化
image.png4、举例
SELECT * FROM t WHERE s = '我';
为了方便大家理解这个过程,我们只分析字符 '我' 在这个过程中字符集的转换
现在看一下在请求从发送到结果返回过程中字符集的变化:
-
- 客户端发送请求所使用的字符集
- 1.1、当客户端使用的是
utf8
字符集,字符'我'
在发送给服务器的请求中的字节形式就是:0xE68891
-
2、服务器接收到客户端发送来的请求其实是一串二进制的字节,它会认为这串字节采用的字符集是
character_set_client
,然后把这串字节转换为character_set_connection
字符集编码的字符。由于我的计算机上character_set_client
的值是utf8
,首先会按照utf8
字符集对字节串0xE68891
进行解码,得到的字符串就是'我'
,然后按照character_set_connection
代表的字符集,也就是 gbk 进行编码,得到的结果就是字节串0xCED2
。 -
- 因为表
t
的列col
采用的是gbk
字符集,与character_set_connection
一致,所以直接到列中找字节值为0xCED2
的记录,最后找到了一条记录
- 如果某个列使用的字符集和character_set_connection代表的字符集不一致的话,还需要进行一次字符集转换
- 因为表
- 上一步骤找到的记录中的
col
列其实是一个字节串0xCED2
,col
列是采用gbk
进行编码的,所以首先会将这个字节串使用gbk
进行解码,得到字符串'我'
,然后再把这个字符串使用
character_set_results
代表的字符集,也就是utf8
进行编码,得到了新的字节串:0xE68891
,然后发送给客户端
- 上一步骤找到的记录中的
- 由于客户端是用的字符集是
utf8
,所以可以顺利的将0xE68891
解释成字符我
,从而显示到我们的显示器上,所以我们人类也读懂了返回的结果
image.png
- 由于客户端是用的字符集是
网友评论