Mysql表字段字符集未设置导致乱码问题
项目场景:
在使用mysql的text类型作为字段类型【未设置编码】,且表结构【设置了编码集】的条件下,查询表这个字段会出现乱码的情况。
问题描述
今日测试小伙伴给题主提出了一个bug,数据库当中的text文本字段在存储json的情况下,代码当中对这个json解析成对象时,对象当中的中文字段出现了乱码的情况。
猜想:
- 当时题主的第一反应是项目当中的数据库连接未配置字符集导致的。一般在项目当中spring的yml文件或者properties文件当中配置。
datasource:
driverClassName: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://xxx:3306/upcloud_wms_jinkong?useSSL=false&serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
username: root
password: root
当时在排查时,发现数据库的连接配置设置了字符编码集,所以乱码问题不是由该配置导致的。
- 排除了spring项目当中的配置后,题主又怀疑是数据库表结构未设置编码集,所以又去排查了数据库的编码集的配置。
CREATE TABLE `xxx` (
`id` bigint NOT NULL AUTO_INCREMENT,
`content` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='test'
但是当查看了数据表结构配置时,发现数据库的表设置了编码集,数据还是出现了乱码。所以也排除掉了数据库表结构设置。
到了此刻题主就有点纳闷了,因为数据库字段的编码集会继承自表的编码集,但是表的编码集分明设置了utf-8mb4的 编码集为什么还会出现乱码的情况了。
原因分析:
在和测试的小伙伴沟通后,发现对方使用的数据库连接工具是Dbeaver,但是在修改数据时将内容文本直接打开,进行编辑保存的。如下图:
在核对了了小伙伴的连接工具后,确认了他的客户端连接工具的编码集也设置了utf8的编码集。这下直接给我整不会了,所有的编码集都是utf8为什么还会出现乱码,但是只要测试同学使用上述的方式保存文本就会出现中文乱码。
解决方案:
在经过一系列的排查后,题主想到了一个大胆的想法,给字段也加上编码集
alter table xxx modify content text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
然后重新让测试同学进行保存,发现后续的数据编码就正常了。但是在我自身进行测试时还是发现了一个问题,就是当测试同学保存完数据后,就算我使用navicat工具进行正常保存还是会出现乱码。对于mysql如果字段未设置编码集,但是在存储数据时未使用表结构上设置的编码集还是会出现字段的编码集和表编码集不一致的情况。
猜测:
因该是测试的连接工具虽然设置了编码集,但是直接在未设置编码集的数据上进行修改时可能会出现问题,不清楚是因为第一次设置进去的数据就是错误的编码集导致的还是因为什么情况,后续的数据修改一直都会使用错误的编码集,所以导致如果不强制设置字段编码集时就会出现乱码的情况。
总结:当然上述的猜测只是只是我个人的经验总结,我只是根据表象进行的猜测,如有错误,希望大家能够指正1