概述

中文乱码是我们日常编程开发中经常会遇到的问题,包括:

  • 浏览器(页面)显示乱码,参考记一次中文乱码排查解决流程
  • Linux系统字体缺失导致中文乱码,参考Linux环境下Selenium截图乱码及字体安装及与字符集区别
  • IDEA console控制台乱码,参考IDEA + Tomcat 8.5中文乱码解决过程
  • 数据库中文乱码,
  • CSV/Excel文件中文乱码,参考BOM及CSV/Excel乱码及从代码上根源解决问题

本文就是一次数据库中文乱码问题记录。

问题

一个很简单的CRUD接口,Postman模拟接口前端传参JSON如下(省略其他字段):

{
    "companyName": "以邑妈测试的公司"
}

接口自是请求成功,去DataGrip里查看一下数据库,发现乱码:

MySQL中文乱码问题记录_MySQL


8个英文?符号,正好对应以邑妈测试的公司中文字符长度。

注,这个表是业务开发时,新增的表。

排查

首先检查当前数据库,其他表里也有中文信息,没有乱码。发现同一个数据库下另一个表结构定义语句如下(省略其他无关信息):

comment '信息表' charset = utf8mb4;

charset

理论上,表结构默认就是UTF-8编码,utf8mb4是UTF-8的增强版。也就是说,这个表结构编码定义可加可不加。

问题已经发生,在不知道解决方案时,总是会如盲头苍蝇诸般尝试。于是修改数据表编码

alter table merchant_app convert to character set utf8mb4;

不行,还是乱码!

character_set

Google搜索,看了不下5篇文档,都说和character_set有关。于是查询字符集:

show variables like '%char%';

输出:

Variable_name

Value

character_set_client

utf8mb4

character_set_connection

utf8mb4

character_set_database

utf8

character_set_filesystem

binary

character_set_results

utf8mb4

character_set_server

latin1

character_set_system

utf8

character_sets_dir

/usr/share/mysql/charsets/

其中character_set_server=latin1看起来就是问题所在。

但是:数据库是已经安装并配置好,是不是最优配置,此时讨论意义不大;数据库不是只有我新增的这一个表,其他表可以正常存储中文数据。

所以绝大多数文章推荐的解决方案:修改MySQL全局配置文件my.ini里的character_set_server=utf8配置项,并重启数据库,就显得有些无厘头。如果是自己本机安装的数据库,搭建本地demo测试项目,出现中文乱码,我们可以放心大胆修改全局配置,并重启数据库。

DataGrip

考虑到上面的中文乱码是Java应用程序通过mysql-connector-java JDBC驱动连接数据库,通过socket提交SQL时才会出现中文乱码。

那我在DataGrip客户端执行提交SQL试试呢?

UPDATE merchant_app SET company_name = '中文' WHERE id = 1;

结果:

MySQL中文乱码问题记录_数据库_02


是正常的!没有乱码!!貌似看到希望的曙光。此时我们再去看看DataGrip的DataSource配置详情看看,在General里URL平平无奇,指定IP和端口。

MySQL中文乱码问题记录_中文乱码_03


进一步查看Advanced便签页:

MySQL中文乱码问题记录_中文乱码_04


也就是说DataGrip默认帮我们在URL里增加characterEncoding=UTF-8配置信息。如果手动修改这个配置项,也就是上面那个character_set_server=latin1

MySQL中文乱码问题记录_中文乱码_05


此时再次执行上面的SQL:

UPDATE merchant_app SET company_name = '中文' WHERE id = 1;

结果:

MySQL中文乱码问题记录_中文乱码_06

结论

修改JDBC connection String,这个配置在yml文件里。之前使用的是jdbc:mysql://10.20.30.40:3306/user,更新为jdbc:mysql://10.20.30.40:3306/user?useUnicode=true&characterEncoding=UTF-8,即可解决问题。

拓展

安装

DBA在安装好MySQL数据库后,需要做一些配置,其中就包括设置character_set_server=utf8character_set_server=utf8mb4。如果有这项配置,在Java应用程序里连接MySQL数据库,即,在Client端连接时,就不需要显式指定characterEncoding=UTF-8,因为此时有MySQL Server端的character_set_server配置给予保证不会出现中文乱码。

如果Server端没有做好调优(事实上,这个算是基础配置,还谈不上调优配置)配置,那就必须在Client端加上characterEncoding配置。

UTF-8 & utf8mb4

MySQL 5.5.3后增加utf8mb4编码,mb4即most bytes 4,用于兼容四字节的unicode。utf8mb4是utf8的超集。

参考