mysql是我们常用的数据库,但是在使用过程中经常会在不同地方遇到中文乱码问题。
此外,mysql8.0版本才开始默认使用utf-8字符集,在之前的mysql5.7版本默认字符集还有latin1的存在。
本文以windows环境下mysql 8.0版本的使用为例,可以跟随本文逐步排查,从而解决以下问题:
- 怎么解决mysql客户端中出现的中文乱码?
- 怎么设置mysql的字符集编码?
- 为什么更改好了my.ini配置文件后没有生效?
查看当前默认字符集
要解决乱码问题,首先要在mysql客户端中查询当前的默认字符集设置,命令如下:
SHOW VARIABLES LIKE 'character%';
正常情况下,查询出的结果应该是下面这样:
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 | utf8mb3 |
| character_sets_dir | C:\Program Files\MySQL\MySQL Server 8.0\share\charsets\ |
+--------------------------+---------------------------------------------------------+
8 rows in set, 1 warning (0.01 sec)
其中各个字段的含义如下:
字段 | 含义 |
---|---|
character_set_client | 客户端发送给服务器的 SQL 语句使用的字符集 |
character_set_connection | 服务器对客户端连接中的字符集进行转换时所使用的字符集 |
character_set_database | 新建数据库时默认使用的字符集 |
character_set_filesystem | MySQL 文件系统交互时的字符集,通常表示为字节存储模式 |
character_set_results | 服务器返回给客户端查询结果时使用的字符集 |
character_set_server | 服务器的默认字符集,新建数据库或表默认使用的字符集 |
character_set_system | MySQL 内部系统表(如 INFORMATION_SCHEMA )使用的字符集 |
character_sets_dir | 存放 MySQL 支持的字符集定义文件的目录路径 |
由上面的信息可知,mysql在不同的层次都可以进行不同的字符集编码设置,
比如:客户端、服务器、数据库、链接等。
只要上面的字符集设置没有统一,就可能在客户端中或者其他地方出现字符乱码。
一般情况下,为防止出现中文乱码,我们会把除character_set_filesystem
、character_set_system
外的字符集都设置为utf8mb4
。
注:如果在前端页面渲染时出现中文乱码,通常的原因是前端页面的编码与浏览器解释页面时所使用的编码不匹配。
修改mysql字符集
修改mysql的字符集有多种方式,修改的作用范围和持久性也各不相同,可以根据自己的情况选择适合的方式。
1.修改配置文件
01 修改配置文件
要修改配置文件,首先要找到配置文件的位置,使用不同安装方式配置文件的路径也不同。
MySQL Installer(Windows):一般会在
C:\ProgramData\MySQL\MySQL Server 8.0
目录生成my.ini
。ZIP 解压安装:不会自动生成
my.ini
,需要手动创建并放置到 MySQL 的安装目录或系统默认位置。
打开my.ini
文件,在对应的标签下添加以下几条,达到永久性的修改字符集配置的效果:
例如:在[mysql]
这个标签下面添加一行行default-character-set = utf8mb4
,注意不要添加错了位置。
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
配置文件对默认字符集的修改是永久性的,修改后需要重启mysql服务,此后每次启动mysql都会以配置文件中修改的字符集作为默认的字符。
02 重新启动mysql服务
有两种方式可以重启mysql服务
-
通过任务管理器重启:
在windows任务管理器的服务中找到mysql的服务启动或停止,这里图中MySQL80是8.0版本的服务名称;
不同安装方式或者安装过程中修改了服务名称会导致服务名不同,根据自己的情况选择。
-
通过windows终端重启服务:
打开cmd或者powershell,通过以下命令来停止、启动mysql服务
net stop mysql net start mysql
03 重新连接mysql
重新连接mysql后,在mysql客户端中再次查询当前字符集设置:
SHOW VARIABLES LIKE 'character%';
此时若结果中都显示为utf8,则字符集已修改成功
若结果中依然存在其他编码规则,详见下文my.ini无效问题
2.用命令修改配置
除了通过修改配置文件来修改默认字符集外,还可以在mysql客户端中通过命令来修改默认字符集,但是这种方式都不是永久性的。
有两种修改方式:
01 修改当前会话(连接)的默认字符集
SET character_set_client = 'gbk';
SET character_set_connection = 'gbk';
SET character_set_results = 'gbk';
SET character_set_server = 'gbk';
SET character_set_database = 'gbk';
以上命令修改的都是当前会话(也就是当前的连接)中的默认字符集。
修改后立即生效,但是会在mysql重新连接之后失效,也就是会恢复到原来的字符集设置。
02 修改当前mysql生命周期的默认字符集
SET GLOBAL character_set_client = 'gbk';
SET GLOBAL character_set_connection = 'gbk';
SET GLOBAL character_set_results = 'gbk';
SET GLOBAL character_set_server = 'gbk';
SET GLOBAL character_set_database = 'gbk';
以上命令修改仅在当前 MySQL 服务的运行周期内有效,需要在重新连接mysql后才会生效,但是会在mysql服务重新启动之后失效。
3.修改数据库、表、字段的字符集
如果需要单独修改某一个数据库、表或字段的默认字符集编码,可以采用下面的方式修改,
这种方式的修改是永久性的,属于对表结构的修改,会保存在数据库中;
修改范围如下:
修改数据库的字符集,会影响其中的数据表、字段的默认字符集;
也就是在新建数据表、字段时,若没有指明字符集,就会使用默认的数据的字符集。
修改数据表的字符集,会影响其中的字段的默认字符集。
修改字段的字符集,仅影响被修改字段的字符集。
01 修改数据库的字符集
通过以下查询语句可以查询出指定数据库的默认字符集以及排序规则。
例:这里查询test
数据库的默认字符集。
SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = 'test';
结果如下:
+-------------+----------------------------+------------------------+
| SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME |
+-------------+----------------------------+------------------------+
| test | utf8mb4 | utf8mb4_unicode_ci |
+-------------+----------------------------+------------------------+
1 row in set (0.00 sec)
通过 ALTER DATABASE
语句来修改数据库的字符集和排序规则。
例:这里修改test
数据库的字符集为gbk
,排序规则为gbk_chinese_ci
。
ALTER DATABASE test CHARACTER SET gbk COLLATE gbk_chinese_ci;
再次查询,如下:
+-------------+----------------------------+------------------------+
| SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME |
+-------------+----------------------------+------------------------+
| test | gbk | gbk_chinese_ci |
+-------------+----------------------------+------------------------+
1 row in set (0.00 sec)
02 修改数据表的字符集
通过查询建表语句,查看数据表的字符集;或通过查询语句,查询出数据表的排序规则。
例1:查询test
数据库的tb
数据表的字符集。
SHOW CREATE TABLE tb;
结果如下:
CREATE TABLE `tb` (
`id` int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
例2:查询test
数据库的tb
数据表的排序规则。
SELECT TABLE_NAME, TABLE_COLLATION
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'tb';
结果如下:
+------------+-----------------+
| TABLE_NAME | TABLE_COLLATION |
+------------+-----------------+
| tb | gbk_chinese_ci |
+------------+-----------------+
1 row in set (0.00 sec)
通过 ALTER TABLE
语句来修改数据库的字符集和排序规则, 例如这里修改test
数据库的tb
数据表字符集为gbk
,排序规则为gbk_chinese_ci
。
ALTER TABLE tb CHARACTER SET latin1 COLLATE latin1_swedish_ci;
03 修改字段的字符集
通过下面的查询语句可以查询出某个字段使用的字符集及排序规则:
SELECT TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'tb' AND COLUMN_NAME = 'age';
例:这里在上面修改tb
数据表的字符集为latin1
之后,查询出的结果。
+------------+-------------+--------------------+-------------------+
| TABLE_NAME | COLUMN_NAME | CHARACTER_SET_NAME | COLLATION_NAME |
+------------+-------------+--------------------+-------------------+
| tb | age | latin1 | latin1_swedish_ci |
+------------+-------------+--------------------+-------------------+
1 row in set (0.00 sec)
通过 ALTER TABLE ... MODIFY COLUMN
修改字段的字符集:
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型 CHARACTER SET 字符集名 COLLATE 排序规则;
-- 例:修改age字段的字符集与排序规则(此语句可同时修改数据类型)
ALTER TABLE tb MODIFY COLUMN age VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
或者,使用CHANGE COLUMN
修改字段的字符集:
ALTER TABLE 表名 CHANGE COLUMN 原字段名 新字段名 字段类型 CHARACTER SET 字符集名 COLLATE 排序规则;
-- 例:修改age字段的字符集与排序规则(此语句可同时修改数据类型、起别名)
ALTER TABLE tb CHANGE COLUMN age age VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
my.ini无效问题
如果修改好了my.ini配置文件,重启mysql服务后,依然在默认字符集查询结果中出现utf8mb4之外的其他字符编码,可以通过以下方式排查。
01 检查windows终端字符编码
-
在系统终端中输入下面的命令,若显示的活动代码页不是
65001
,则表示不是utf8编码。chcp
-
通过右击终端打开属性,点击选项,查看当前代码页是否为65001(UTF-8)。
若如下图,显示为gbk,则说明mysql客户端的默认字符集受到了系统终端的默认字符集的影响,从配置文件的utf8mb4
变成了GBK
。
这种情况还可能导致Navicat中不会出现中文乱码,但是在mysql客户端中会出现中文乱码,就是因为客户端受到了windows系统终端的字符编码的影响。
02 修改windows终端编码
不建议修改整个操作系统的字符编码,有可能会导致系统中的其他应用中出现中文乱码。
windows终端的字符编码有两种修改方式,但持久性不同:
-
临时修改
在终端中输入下面的命令,可以临时修改终端的字符编码,但是终端重启后会失效:
chcp 65001
如果不想永久修改终端的字符编码,但又希望不用每次运行终端时都更改其字符编码,可以创建一个快捷方式:
在对象位置中输入下方路径,可以达到每次启动mysql客户端时,自动更改终端的字符编码的效果。
从而不影响mysql的默认字符集,并且只需要输入密码即可连接mysql。
(其中
"C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe"
需要根据自己的mysql.exe
的实际位置更改):cmd /c chcp 65001 && "C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe" -u root -p
-
永久修改
打开注册表:按
win+R
键,然后输入regedit
找到:
HKEY_CURRENT_USER
->Console
->%SystemRoot%_system32_cmd.exe
双击后在右侧找到
CodePage
,双击后,选择十进制,然后将值改为65001,这样就把cmd终端的字符编码永久修改为了utf8。
03 检查mysql启动时使用的配置文件
如果my.ini配置无误,并且系统终端的字符编码也是uf8,但是mysql的客户端中还是出现中文乱码,可能是mysql客户端在启动时没有使用之前修改好的配置文件,接下来通过下面的方式来排查。
打开注册表:按win+R
键,然后输入regedit
找到:HKEY_LOCAL_MACHINE
->CurrentControlSet
->Services
->MySQL80
双击后在右侧找到ImagePath
,双击查看其中的路径是否为正确的my.ini路径,如果不是就将其修改为正确的路径
然后重启mysql服务,再次检查mysql的默认字符集。
至此,有关mysql的字符集设置的问题就介绍完了,应该能够解决大部分的中文乱码问题。