swift 发布于 2023年06月08日
Emoji 就是我们常说的表情符号,如果你的产品是经常处理 UGC 内容的话,就要特别注意它的处理,这次就和大家分享一个我实际遇到过的一个问题。
起因发现这个问题的起因,是之前的一个微信小程序产品,有一段时间经常有用户反馈无法登录。 可是自己尝试复现这个问题很多次,都没有成功。起初呢,没太当回事,也是因为其他开发工作实在太多了,有点忙不过来。
但是,反馈类似问题的用户一直不断,在某一天我想着专门抽出时间来处理这个问题。 还是按照以前的方法,用我自己的微信账号,在小程序各种边界条件下调用后端的登录接口。还是一样的结果,依然没有复现出问题。
每次陷入这种死局时,我一般会去干点别的事,喝杯咖啡,出去走了走。 果然,这个办法还是管用,回来时候我换了一个思路。
既然我自己的场景无法复现问题,我就从这些用户的信息分析开始。 小程序的反馈系统是能看到用户的 Open ID 的。 从这个 Open ID 自然就能追踪到后端数据库具体的记录。
查看这个用户对应的数据记录,用户名确实没有正确的写入,那么我就尝试直接在 MySQL 会话中直接把他的用户名设置进来:
结果是在我的预期之外,数据库竟然报错了:
我继续用同样的方式直接用 SQL 设置我自己账户的名字,结果却是成功设置。 然后我把之前反馈无法登录的用户名都对比了一下,发现了真正的问题。 这些无法登录的用户名都有一个共性,就是用户名中都带有 Emoji 符号。
如何解决找到问题根源后,经过了一番搜索,也找到了解决方案。导致这个错误的原因是 MySQL 使用了 utf8 字符集。 简单来说 MySQL utf8 字符集只支持 1-3 字节长度的数据,而 Emoji 恰好是 4 字节长度,导致了编码不匹配,造成数据库报错。
解决方法也很简单, 以 MySQL 为例,将原有的数据库和表使用的字符集改成 utf8mb4 就可以了。 如果你使用的不是 MySQL 就按照你当前使用的数据库实际情况来处理。
utf8mb4 - 4字节 UTF-8 编码, 比早期的 utf8 编码多一个字节,用来表示更多的字符。 在 MySQL 的语境下,实际上 utf8 是 utf8mb3 的一个别名,这样的名称对比,你就会觉得 utf8mb4 这个名字不那么奇怪了。
关于字符集准确的定义, MySQL 官网有明确的说明:
utf8mb4 - https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8mb4.html
utf8mb3 - https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8mb3.html
感兴趣的伙伴可以自行去查看官方文档。
那么简单说一下如何将我们之前用 utf8 创建的数据库,转换成 utf8mb4。
首先在库级别和表级别修改相应的字符集:
ALTER DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `table_name` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
然后还需要修改数据库设置 my.inf
, 有些文章这样设置:
default-character-set=utf8mb4
在我自己的实际情况,用 default-character-set 会在重启数据库的时候报错, 还有一种方式是通过 loose-default-character-set 来设置:
loose-default-character-set=utf8mb4
实在没有时间深究这个设置的问题了,总之, 这两处改动完成之后,重启数据库服务,Emoji 就可以正常使用了。 我们也可以通过 MySQL 看到当前数据库的字符集:
+--------------------------+--------------------+
| Variable_name | Value |
+--------------------------+--------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+--------------------------+--------------------+
rows in set (0.00 sec)
-----------------------------------
如果这样还不行的话,某些情况下还需要对表中单独的 Column 进行设置
基本上这几步操作做完之后, Emoji 就可以正常写入数据库了。
写在最后总的来说,如果你的后端使用 MySQL 数据库。我们新创建的应用,都应该使用 utf8mb4 字符集。 以前的 3 字节 utf8 更适用于早年 Web 桌面互联网的时代,那时候基本不会使用 Emoji 这些超字符集。 但现在的互联网用户,这类新字符的输入占比是非常高的,特别是 UGC 类型的应用。 即使你的后端数据库用的不是 MySQL,我相信也会存在类似的情况。
通过这个问题,我们基本上可以建立一个意识,就是 Emoji 使用的字符集是需要特别注意的,在其他内容都能正常保存的情况下, Emoji 是有可能因为你存储字符集的问题,出现错误的。
并且现在用户使用 Emoji 的频率并不低,比如我这个出现登录问题的小程序,就有10%以上的用户名中含有 Emoji,这种问题还并不好调试,如果不是因为用户登录这个关键入口,可能都很难发现问题。
如果大家有什么相关的经验,也欢迎在留言区补充。
如果你觉得这篇文章有帮助,还可以关注微信公众号 swift-cafe,会有更多我的原创内容分享给你~
本站文章均为原创内容,如需转载请注明出处,谢谢。
![]() 发现更多精彩 swift-cafe |