最近,我碰到了一个让人头疼的bug。用Rails操作MariaDB数据库时,我试图保存一个UTF-8编码的字符串“😃”,结果数据库报错说字符串值不正确。我一开始是懵的,因为客户端、服务器、数据库,包括要保存的字符串,都是UTF-8编码的,理论上应该没问题。
问题出在MySQL的“utf8”编码实际上并不是真正的UTF-8。它最多只支持3个字节的字符,而标准UTF-8可以支持到4个字节。MySQL在2010年推出了“utf8mb4”来解决这个问题,但这个新编码并没有得到广泛宣传,导致很多人还在错误地使用“utf8”。
这里要强调,如果你在使用MySQL或MariaDB,记得把编码改成“utf8mb4”,别再用“utf8”了。
接下来聊聊编码。计算机用0和1来存储文本,就像字符“C”存储为“01000011”。显示字符时,计算机会先读取这些二进制,转换成数字,再到Unicode字符集中找到对应的字符。Unicode字符集非常庞大,包含了上百万字符。
UTF-8是一种很节省空间的编码方式。比如字符“C”在UTF-8中只需要8位,而不常用的字符可能需要32位。这样一篇文章用UTF-8编码,可能只占UTF-32的四分之一空间。
但MySQL的“utf8”和其他程序不兼容,它所谓的“utf8”可能并不是真正的UTF-8。MySQL的“utf8”编码问题可以追溯到2003年,当时UTF-8标准还未统一。MySQL开发者可能是想优化性能,结果却弄巧成拙。
总之,如果你在用MySQL或MariaDB,记得用“utf8mb4”,别被“utf8”坑了。这个错误太隐蔽,我花了整整一周才找到问题所在,希望我的分享能帮你避免类似的坑。