MySQL编码的选择问题

要说PHP最好的伴侣是谁?肯定非MySQL莫属。很多年前大家还习惯将学习PHP叫学习LAMP,后来又叫LNMP。现在因为开发分工越来越细周围很少听到这种叫法。Linux+Nginx+MySQL+PHP每一层都有专门的人在维护,这也是未来精细化分工的一种趋势。我第一次用MySQL的时候MySQL的版本还是4.1,这几年见证了MySQL从4.1到5.7时代的蓬勃发展,MySQL 5.6 也是迄今为止我个人比较信赖的数据库版本。

现在MySQL成了国内互联网公司的标配,在早年国内的互联网公司都相当依赖IBM的小型机、Oracle数据库、EMC存储设备,因为市场垄断所以这三家公司经常坐地起价国内厂商不堪重负,再加上这三家公司都来自美帝国主义随便都能留个后门让人不放心。09年的时候阿里云的王坚博士率先喊出去IOE的口号,慢慢的百度和腾讯也开始效仿。有BAT做技术担当,国内互联网纷纷响应,这些年已经很少听到IOE的消息了(EMC存储设备我没做过多的了解,IBM的小型机、Oracle数据都被Linux集群和MySQL集群取代)。所以Linux和MySQL已经成为程序员标配技能。

在使用MySQL的过程中会遇到很多编码方面的问题,往往编码问题带来的影响都是致命的,轻则被黑客攻击,重则用户流失。

今天来说说Emoji表情,事情的起因还是用户上报说我们的系统无法提交Emoji表情。一接到这个反馈就觉得诡异,因为在设计数据库的时候我就考虑过会有Emoji表情的问题,所以MySQL数据库的编码和表的编码都选择的utf8mb4,这种编码支持Emoji表情。经过测试我发现确实是不行,用户提交Emoji表情不会报错,但是返回数据的时候Emoji表情之后的数据都不显示,数据被截断了。比如用户输入『这是 👿你怕不怕』,数据库中只会存『这是』。

这个问题很快就被解决了,因为如果数据库存储出现编码问题,只可能是下面三种原因:

  1. 数据库编码问题;
  2. 表字段编码问题;
  3. MySQL连接时的编码问题;

很快就能排除1和2,然后在代码中检查MySQL的连接配置,发现默认的数据库连接编码是utf8,将编码改为utf8mb4后问题圆满解决。

其实这是一个很小的问题,但是带来的影响不容忽视。很多网站是不会考虑Emoji表情的,用户提交Emoji表情要么会报错,要么数据会被截断,黑客也可以利用这些信息寻找攻破网站的方法。数据无小事,曾经我升级测试环境MySQL的版本时没有及时的备份数据库,导致升级之后原来的数据库文件无法使用,测试环境也存储了大量有用的数据。得知数据丢失后一脸懵逼,别说恢复数据了,思路都理不清。最后还是同事帮忙将数据恢复,这也是我职业生涯最惨痛的一次教训。

MySQL编码最好选择utf8mb4,除了能存储Emoji表情外,还能存储很多我们未知的符号。如果你的MySQL版本不支持utf8mb4(MySQL5.5 之后才支持该格式),你需要在代码中处理Emoji字符,可以做转码等。