在MySQL中,不要使用“utf8”。使用“utf8mb4”

今天的错误:我试图将一个UTF-8字符串存储在MariaDB“utf8”编码的数据库中,并且引发了一个奇怪的错误:

Incorrect string value: ‘xF0x9Fx98x83 <…’ for column ‘summary’ at row 1

这是UTF-8客户端和UTF-8服务器,位于UTF-8数据库中,具有UTF-8编码规则。字符串“?”是有效的UTF-8。

但问题是:MySQL的“ utf8 ” 不是UTF-8。
“utf8”编码仅支持每个字符三个字节。真正的UTF-8编码 – 每个人都使用,包括你 – 每个字符最多需要四个字节。
MySQL开发人员从未修复过这个bug。他们在2010年发布了一个解决方法:一个名为“ utf8mb4 ” 的新字符集。
当然,他们从未公布过这个(可能是因为这个bug太尴尬了)。现在,Web上的指南建议用户使用“utf8”。所有这些指南都是错误的。
简而言之:

MySQL的“utf8mb4”表示“UTF-8”。

MySQL的“utf8”意味着“专有字符编码”。此编码不能编码许多Unicode字符。

我将在这里做一个彻底的陈述:目前使用“utf8”的所有 MySQL和MariaDB用户实际上应该使用“utf8mb4”。没有人应该使用“utf8”。

什么是编码?什么是UTF-8?

Joel on Software写了我最喜欢的介绍(https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/
)。我会缩减它。

Computer(计算机)将文本存储为1和0。本段中的第一个字母存储为“01000011”,你的计算机显示为“C”。你的计算机分两步选择“C”:
1.你的计算机读取“01000011”并确定它是数字67.这是因为67被编码为“01000011”。
2.你的计算机在Unicode 字符集中查找字符编号67 ,并且发现67表示“C”。

当我键入“C”时,我的结果发生了同样的事情:
1.我的计算机将Unicode字符集中的“C”映射到67。
2.我的计算机编码为 67,向此Web服务器发送“01000011”。
字符集是一个解决的问题。几乎互联网上的每个程序都使用Unicode字符集,因为没有动机使用另一个。

但编码更像是一种判断。Unicode具有超过一百万个字符的插槽。(C和“?”是两个字符)最简单的编码(utf-32)使每个字符占用32位。这很简单,因为计算机已经把32位的组当作数字处理了很多年,而且他们真的很擅长。但它没用:这是浪费空间。
UTF-8节省空间。在UTF-8中,像“C”这样的常见字符占8位,而像“其他字符需要16或24位。像这样的博客文章在UTF-8中占用的空间比在UTF-32中少四倍。所以加载速度快四倍。
你可能没有意识到,但我们的计算机在幕后同意了UTF-8。如果他们没有,然后当我输入
“?”时,你会看到一堆随机数据。
MySQL的“utf8”字符集与其他程序不一致。当他们说“?”时,它会犹豫。

一点MySQL的历史

为什么MySQL开发人员使“utf8”无效?我们可以通过查看提交日志来猜测。
MySQL从版本4.1开始支持UTF-8 。那是2003年 – 在今天的UTF-8标准之前,RFC 3629。
以前的UTF-8标准RFC 2279每个字符最多支持6个字节。MySQL开发人员在2002年3月28日的MySQL 4.1的第一个预发行版本中编写了RFC 2279 。
然后在9月对MySQL的源代码进行了一次神秘的,一字节的调整:“UTF8现在只能处理3个字节的序列。”

是谁提交了这个?为什么?我说不出来。MySQL的代码库在采用Git时似乎丢失了旧的作者名称。(MySQL过去常常使用BitKeeper,就像Linux内核一样。)2003年9月左右的邮件列表中没有任何内容可以解释这一变化。
但我可以猜到。

早在2002年,如果用户可以保证表中的每一行具有相同的字节数,MySQL就会为用户提供速度提升。为此,用户会将文本列声明为“CHAR”。“CHAR”列始终具有相同的字符数。如果你输入的字符太少,它会在末尾添加空格; 如果你输入太多的字符,它会截断最后的字符。

MySQL开发人员第一次尝试使用UTF-8时,每个字符的后六个字节,他们可能会犹豫不决:一个CHAR(1)列需要六个字节; CHAR(2)列需要12个字节; 等等。
让我们明确一点:从未发布的初始行为是正确的。它得到了很好的记录和广泛采用,任何理解UTF-8的人都会同意这是正确的。

但显然,MySQL开发人员(或商人)担心一两个用户会做两件事:
1.选择CHAR列。(CHAR格式现在是遗物。当时,使用CHAR列,MySQL速度更快。直到2005年,它不是。)
2.选择将这些CHAR列编码为“utf8”。
我的猜测是MySQL开发人员打破了他们的“utf8”编码来帮助这些用户:1)试图优化空间和速度的用户; 2)未能优化速度和空间。
没人赢。想要速度和空间的用户使用“utf8”CHAR列仍然是错误的,因为那些列仍然比它们原来更大更慢。想要正确性的开发人员使用“utf8”是错误的,因为它无法存储
“?”
一旦MySQL发布了这个无效的字符集,它就永远无法解决它:这将迫使每个用户重建每个数据库。MySQL最终在2010年发布了UTF-8支持,名称不同:“utf8mb4”。

为什么这么令人沮丧

很明显,本周我很沮丧。我的bug很难找到,因为我被“utf8”这个名字所迷惑。而且我不是唯一一个 – 我在网上发现的几乎所有文章都将“utf8”称为UTF-8。
名称“utf8”始终是错误的。这是一个专有的字符集。它创造了新问题,并没有解决它要解决的问题。
这是虚假的广告。

免责申明:
1. 本站所有教程、文章分享目的仅供大家学习和交流,资源连接来自于网络,非本站发布,本站也不存储任何资源!
2. 如有无法查看或链接失效,烦请报告联系管理员处理!
3. 本站无法保证资源质量及其时效性,恕不接受任何提问。
4.本站即不保存任何资源,也不对任何链接作品负责,希望大家赞助本站,费用仅维持本站的日常运营所需!
5. 百码云无法保证文章教程或资源的完善与安全,请自行检测解决。
6. 通过本站收集链接的相关资源,严禁杜绝任何形式的正式商业用途,请前往官方购买。
7. 但凡通过本站链接导航下载的任何作品,虽不归本站所有,但在研究学习的前提下,请务必在下载24小时后删除。
百码云资源站仅提供学习的平台,所有资料均来自于网络,版权归原创者所有!本站不提供任何保证,并不承担任何法律责任,如果对您的版权或者利益造成损害,请提供相应的资质证明,我们将于3个工作日内予以删除。本文章采用BY-NC-SA 4.0 《国际知识共享署名许可协议4.0》 进行许可 。
百码云 » 在MySQL中,不要使用“utf8”。使用“utf8mb4”

提供互联网优质的链接集合站点

关于权限 站内帮助