迁移后中文乱码,MariaDB 默认字符集与 MySQL 配置区别在哪里?

文章导读
从 MySQL 迁移到 MariaDB 后中文乱码的根本原因是字符集配置差异,根据 2024 年 9 月腾讯云开发者社区的实测,80% 以上的乱码问题源于 character_set_server 未统一设置为 utf8mb4。
📋 目录
  1. 原因分析
  2. 解决方案
  3. 注意事项
  4. 参考来源
A A

迁移后中文乱码,MariaDB 默认字符集与 MySQL 配置区别在哪里?

核心结论:从 MySQL 迁移到 MariaDB 后中文乱码的根本原因是字符集配置差异,根据 2024 年 9 月腾讯云开发者社区的实测,80% 以上的乱码问题源于 character_set_server 未统一设置为 utf8mb4。

原因分析

迁移后中文乱码的本质是客户端与服务端字符集不一致。根据 2026 年 4 月 17 日的技术文档,MySQL 迁移后 SELECT 中文显示问号或乱码,根本原因是客户端与服务端字符集不一致,需逐层验证 client/connection/results/table/column 五层编码是否统一为 utf8mb4。

MariaDB 与 MySQL 在默认字符集配置上存在关键差异:

  • MySQL 5.7 默认字符集为 latin1,MySQL 8.0 开始推荐 utf8mb4
  • MariaDB 10.1 版本中,varchar(N) 类型字段的缺省值与 MySQL 5.5/5.6 不同,MariaDB 10.1 没有默认值,而 MySQL 5.5/5.6 的默认值是空串''
  • 根据 2025 年 6 月 19 日 TXSQL MariaDB 内核与 MySQL 5.6 兼容性说明,MariaDB 的 Binlog 默认采用 row 格式,而原生 MySQL 5.6 默认采用 statement 格式

具体报错信息示例:当字符集不匹配时,常见错误为中文显示为"???"或"",执行 SHOW VARIABLES LIKE'character_set%'可发现 character_set_client、character_set_connection、character_set_results 三连项不统一为 utf8mb4。

解决方案

第一步:确认服务器默认字符集

执行以下命令检查当前字符集配置:

SHOW VARIABLES LIKE'character_set%';

重点关注 character_set_server 和 collation_server。若不是 utf8mb4,需修改配置文件(如/etc/my.cnf 或/etc/mysql/mysql.conf.d/mysqld.cnf):

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

⚠️ 注意:仅改客户端配置(如 [client] 段)不能解决表/列存储层乱码,必须确保 character-set-server 生效且重启 mysqld。根据 2024 年 9 月 2 日腾讯云开发者社区的建议,MariaDB 还需添加 skip-character-set-client-handshake 参数。

第二步:检查并修正已有数据库、表、列的字符集

即使服务端默认设为 utf8mb4,迁移前创建的库/表/列仍可能沿用旧字符集。逐级检查并转换:

-- 查库字符集
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'your_db';

-- 查表字符集
SHOW CREATE TABLE your_table;

-- 查字段字符集
SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'your_db' AND TABLE_NAME = 'your_table';

修正顺序必须是:库→表→列:

ALTER DATABASE your_db CHARACTER SET = utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

⚠️ 注意:CONVERT TO 会重写整张表,大表需评估锁表时间。

迁移后中文乱码,MariaDB 默认字符集与 MySQL 配置区别在哪里?

第三步:调整连接属性与编码转换

临时修复:执行 SET NAMES utf8mb4;(等价于同时设 client/connection/results),立刻生效,但仅对当前会话有效。

永久修复方案因客户端类型而异:

  • MySQL Workbench:Connection → Advanced → Others 添加 characterSet=utf8mb4
  • 命令行:加--default-character-set=utf8mb4 参数
  • JDBC:URL 必须显式带上参数:?useUnicode=true&characterEncoding=utf8mb4,缺一不可

第四步:重新导出 SQL 文件(如已损坏)

如果 mysqldump 导出的 SQL 文件本身含乱码,说明 dump 时没指定源库字符集。根据 2026 年 4 月 17 日的技术文档,mysqldump 默认按 latin1 读表结构和数据,遇到 utf8mb4 表就直接错位转义。

重导出必须加--default-character-set=utf8mb4 参数,且该参数要放在 mysqldump 命令最前面(位置敏感):

mysqldump --default-character-set=utf8mb4 -u root -p your_db > backup.sql

验证导出文件编码:用 file -i your.sql 看是否为 charset=utf-8;用 head -n 20 your.sql | grep CHARSET 检查 CREATE TABLE 语句末尾是否有 DEFAULT CHARSET=utf8mb4。

注意事项

  • 坑 1:仅改配置文件不重启无效:根据 2024 年 9 月 2 日腾讯云开发者社区反馈,修改/etc/my.cnf.d/server.cnf 后必须执行 systemctl restart mariadb 重启数据库,否则配置不生效。
  • 坑 2:字段级字符集优先级高于表级:表级字符集只是默认值,真正决定存储编码的是字段自身的 CHARACTER SET 属性。迁移脚本若用 CREATE TABLE DEFAULT CHARSET=utf8mb4,但字段定义里写了 VARCHAR(255) CHARACTER SET latin1,那这个字段仍按 latin1 存储。检查方法:SHOW FULL COLUMNS FROM table_name;,看 Collation 列是否为 utf8mb4_0900_ai_ci 类型(不是 latin1_swedish_ci)。
  • 坑 3:大表转换需评估锁表时间:ALTER TABLE CONVERT TO CHARACTER SET 会锁表,大数据量慎用。根据 2026 年 4 月 12 日的建议,若只需改列字符集(如只改某 varchar 字段),用 MODIFY COLUMN 更精准。
  • 坑 4:已用错编码导出无法靠 iconv 转换:因为 latin1 到 utf8mb4 不是简单字节映射,而是逻辑错位,需从原库重新 dump。
  • 坑 5:MariaDB 与 MySQL GTID 不兼容:根据 2025 年 6 月 19 日 TXSQL 兼容性说明,MariaDB 的 GTID 和 MySQL 5.6 的 GTID 不兼容,即 MySQL 不能作为 MariaDB 的从库,迁移时需注意复制架构调整。

参考来源

来源:腾讯云开发者社区 - MariaDB 中文乱码之解决思路(2024 年 9 月 2 日)

来源:技术文档 - 如何解决 mysql 迁移后中文乱码问题_统一服务器与客户端字符集(2026 年 4 月 12 日发布)

来源:技术文档 - MySQL 迁移后发现字符集乱码怎么办_调整连接属性与编码转换(截至 2026 年 4 月 17 日)

来源:TXSQL 官方文档 - TXSQL MariaDB 内核与 MySQL 5.6 兼容性说明(2025 年 6 月 19 日)