如何在 mysql 数据库中支持完整的 unicode
你在你的数据库中使用 mysql 的 utf8 字符集吗? 在这篇文章中,我将解释为什么你应该改用 utf8mb4,以及如何去做。
utf-8
utf-8编码可以表示unicode字符集中的每一个符号,范围从u 000000
到u 10ffff
。 那是 1,114,112 个可能的符号。 (并非所有这些 unicode 代码点都已分配字符,但这并不妨碍 utf-8 能够对它们进行编码。)
utf-8 是一种可变宽度编码;可以参考unicode 字符集和 utf-8、utf-16、utf-32 编码这篇文章 它使用一到四个 8 位字节对每个符号进行编码。 具有较低数字代码点值的符号使用较少的字节进行编码。 这样,utf-8 针对使用 ascii 字符和其他 bmp 符号(其代码点范围从 u 000000
到 u 00ffff
)的常见情况进行了优化——同时仍然允许星体符号(其代码点范围从 u 010000
到 u 10ffff
) 被存储。
mysql 中的 utf8
很长一段时间,我一直在为数据库、表和列使用 mysql 的 utf8 字符集,假设它映射到上述 utf-8 编码。 通过使用 utf8,我可以在我的数据库中存储我想要的任何符号——或者我是这么认为的。
在写 javascript 的内部字符编码时,我注意到无法将 u 1d306 tetragram for center (𝌆)
符号插入到该站点后面的 mysql 数据库中。 我尝试更新的列具有 utf8_unicode_ci
排序规则,并且连接字符集设置为 utf8。
mysql> set names utf8; # just to emphasize that the connection charset is set to `utf8`
query ok, 0 rows affected (0.00 sec)
mysql> update database_name.table_name set column_name = 'foo𝌆bar' where id = 9001;
query ok, 1 row affected, 1 warning (0.00 sec)
rows matched: 1 changed: 1 warnings: 1
mysql> select column_name from database_name.table_name where id = 9001;
-------------
| column_name |
-------------
| foo |
-------------
1 row in set (0.00 sec)
内容在第一个 astral unicode
符号处被截断,在本例中为 𝌆
— 因此,尝试插入 foo𝌆bar
实际上插入的是 foo
,导致数据丢失(并可能引入安全问题;见下文)。 mysql 也返回一条警告消息:
mysql> show warnings;
--------- ------ ------------------------------------------------------------------------------
| level | code | message |
--------- ------ ------------------------------------------------------------------------------
| warning | 1366 | incorrect string value: '\xf0\x9d\x8c\x86' for column 'column_name' at row 1 |
--------- ------ ------------------------------------------------------------------------------
1 row in set (0.00 sec)
事实证明,mysql 的 utf8 字符集仅部分实现了正确的 utf-8 编码。 它只能存储由一到三个字节组成的 utf-8 编码符号; 不支持占用四个字节的编码符号。
由于星体符号(其代码点范围从 u 010000
到 u 10ffff
)在 utf-8 中均由四个字节组成,因此我们不能使用 mysql 的 utf8 实现来存储它们。
这不仅会影响 𝌆
字符,还会影响更重要的符号,例如 u 01f4a9 pile of poo (💩)
。 总共有 1,048,575 个可能的代码点是我们不能使用的。 事实上,mysql 的 utf8 只允许我们存储所有可能的 unicode 代码点的 5.88% (0x00ffff 1) / (0x10ffff 1)
。 正确的 utf-8 可以编码所有 unicode 代码点的 100% 。
mysql 的
utf8
编码命名很笨拙,因为它与正确的utf-8
编码不同。 它不提供完整的 unicode 支持,这可能会导致数据丢失或安全漏洞。
mysql 中的 utf8mb4
幸运的是,mysql 5.5.3(2010 年初发布)引入了一种名为 utf8mb4 的新编码,它映射到正确的 utf-8,因此完全支持 unicode,包括星体符号。
我们可以参考 mysql 从 utf8 切换到 utf8mb4 这篇文章来对编码进行切换。
总结
永远不要在 mysql 中使用 utf8——总是使用 utf8mb4。 更新数据库和代码可能需要一些时间,但绝对值得付出努力。 为什么要任意限制可以在数据库中使用的符号集? 为什么每次用户输入星体符号作为评论或消息的一部分或我们存储在数据库中的任何内容时,都会丢失数据? 没有理由不在所有地方争取完全的 unicode
支持。 做正确的事,使用 utf8mb4。 🍻
转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处
本文地址:
相关文章
如何在 mysql 中声明和使用变量
发布时间:2024/03/26 浏览次数:115 分类:mysql
-
当你需要在 mysql 中的脚本中存储单个值时,最好的方法是使用变量。变量有不同的种类,有必要知道何时以及如何使用每种类型。
发布时间:2024/03/26 浏览次数:176 分类:mysql
-
本教程演示了如何在 mysql 中重置自动增量。
在 mysql 中使用 mysqladmin 刷新主机解除阻塞
发布时间:2024/03/26 浏览次数:82 分类:mysql
-
你将了解阻止主机的原因。此外,通过使用 phpmyadmin 和命令提示符刷新主机缓存来解除阻塞的不同方法和效果。
发布时间:2024/03/26 浏览次数:199 分类:mysql
-
本教程演示如何在 mysql 中转换为整数。