目录
问题描述
工作过程中,突然收到短信和邮件 5xx 报警。通过 5xx HTTP 状态码排查 Nginx 日志、业务日志发现报如下错误:
问题分析
1 初步看,应该是说更新 name 写入 utf8 编码的 “\xF0\x9F\x92\x95” 失败了。
2 那 utf8 编码的字符串 “\xF0\x9F\x92\x95” 是什么呢?通过排查发现这个是字符串编码的是 emoji 符号,该 emoji 符号代表两颗心的意思。
上面的 emoji 结果是从 Emoji Unicode Tables 获取的,地址如下:
https://apps.timwhitlock.info/emoji/tables/unicode#block-6a-additional-emoticons
3 再次看,应该是用户想通过代表两颗心的 emoji 符号来更新 name 字段。
4 那为什么用户通过代表两颗心的 emoji 符号来更新 name 字段失败了呢?从 两颗心的 emoji 符号的 utf8 编码是 “\xF0\x9F\x92\x95” 字符串,可以看到 emoji 符号是 4 个字符。
5 那为什么编码为 4 个字符的 emoji 更新 name 的时候失败呢?由于存储 name,使用的数据库是 mysql,我们查看 user 表的字段编码是 utf8。
6 那为什么 utf8 编码的 user 表不能写入 4 个字符的 emoji 呢?通过如下命令查看 utf8 编码下,能写入的字符最大个数。
select * from information_schema.CHARACTER_SETS where CHARACTER_SET_NAME = 'utf8';
从图中可以看到 utf8 编码最大支持 3 个字符的写入。
7 最终看,由于 user 表是 utf8 编码最多支持 3 个字符的写入,不支持 4 个字符编码的 emoji 符号的写入。
问题解决
既然是 user 表不支持 4 个字符编码的 emoji 符号的写入,我们只需要将 user 表修改成支持 4 个字符编码的 emoji 符号的写入。
MySQL 在 5.5.3 之后的版本支持了一种新的字符编码:utf8mb4。我们可以查看 utf8mb4 编码最多支持多少字符。
select * from information_schema.CHARACTER_SETS where CHARACTER_SET_NAME = 'utf8mb4';
从图中可以看到最大支持4个字符的写入。所以 utf8mb4 编码能解决 emoji 表情符号的写入。
这块只需要将 user 表的编码修改成 utf8mb4,命令如下:
ALTER TABLE user CONVERT TO CHARACTER SET utf8mb4;
问题扩展
utf8mb4 编码在一些字符的存储消耗大于 utf8编码,如果说表需要存储 emoji 使用 utf8mb4 编码,不需要建议使用 utf8 编码。