1.2016年11月15日(周二),我被经理外派出差渝北金开大道,任务:解决那边的一个数据库乱码异常
2.那边的负责人描述:数据库原是utf8编码,他为了兼容emoji表情,改为utf8mb4,之后出现编码异常
3.数据库是mysql
4.程序人生第一次review别人的代码
第一步:UTF8与UTF8MB4编码的关系
在mysql中,utf8mb4是utf8的子集,之间是可以切换的
第二步:检查异常字符
出现编码异常的只有中文
如果是emoji表情编码乱码还可以解释,为啥是中文乱码
中文在utf8mb4和utf8中同为三个字节
第三步:异常排查
前注:因为是线上环境,数据库和服务器环境都不让动,BTrace工具(http://baike.baidu.com/link?url=DZj--BJ0_Cl_33XFWG0ZBizqClhnKOUQ_CocRZsdJXKXHSdlySe1iRB1A4LE90Tt9isDedr0GGFO1f0iuIRoRa)用不上
1.备份数据,转存到备用测试服务器
2.在测试服存储中文字符,一切正常
3.检查正式服务器和测试服务器的Nginx、Tomcat配置,数据库链接url,一模一样
4.我要求他打印出sql执行情况,console只打印sql的配置:http://www.zuidaima.com/blog/2998561964854272.htm,catalina.log中显示insert时中文已经乱码了
PS:需要检查sql执行情况时,写个log4j.properties传到服务器上,重启一下就可以看到了,不需要了删除即可
5.我冤枉了数据库
难道是打包的问题?
1.检查eclipse的编码,还是utf8,检测分割符,是unix的分隔符,完全符合linux的环境
2.重新打个包传到测试服务器,经测试乱码
3.好吧,数据库接到测试服务器,本地开启调试,中文乱码
代码有问题!
我问了一句那边的负责人:你发布最后一个版本时写了代码没
他说写了的,然后把代码翻给我看
web.xml的过滤器中约定了全文编码为utf8
在java代码中又处理一次编码
然而就是这个多余的编码
source.getBytes(),"UTF-8"
解释这句代码:getBytes不传编码,默认会按照ISO-8859-1来解析,再转回UTF8
把他的代码注释传到测试服,测试,正常了。
总结:
mysql如果是utf8和utf8mb4切换引发编码异常的,都好好检查自己的代码,这个锅,mysql和eclipse都不背。