mysql 额外加入一个 utf8mb4 数据类型,而不是原地升级 utf8?

2019-09-2508:51:55数据库教程Comments2,940 views字数 1643阅读模式

作者:大宽宽文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

MySQL为什么在这个地方犯2。以下内容仅仅为一种猜测。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

先说一下utf8的标准,早期是用1~6个byte来表示一个字符。所以最早的MySQL实现,一个Char是用6个Bytes去实现的。这是正确的做法。但是MySQL为了性能,希望用户使用等长度的字符列。也就是说,一个字符如果用不到6个byte,存储里就会被填充空白符号。学过计算机的人都会明白等长字符,用数组的索引值去找到数据会非常快。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

早期的RFC2279规定一个UTF8字符被编码为1~6个byte。后来才改成了1~4个。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

为此,MySQL甚至搞过一个“static-format“的存储结构,就是用定长数据来加速数据访问。(但这个东西只能用在MyISAM上,那时候MySQL还没收InnoDB)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

15.2.3.1 Static (Fixed-Length) Table Characteristics​dev.mysql.com文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

但也很容易看出来,这么干实在是太浪费空间了。绝大部分的英文用utf8编码1个byte就搞定了,中文等字符是3个byte。在1Charater = 6Byte的设计里,再加上2000年初时存储并不便宜,谁看了都会心疼。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

好,基础讲完,再说历史。让我们回到2002年。MySQL计划在4.1版本支持utf8。4.1的早期开发版本用最多6个byte表示一个utf8字符,这是对的。但是MySQL不知道脑子里抽了哪根筋,在2002年9月27日,for no particular reason,搞出这么一个commit,强制让utf8编码只能处理最多3个byte的序列。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

mysql 额外加入一个 utf8mb4 数据类型,而不是原地升级 utf8?

See:UTF8 now works with up to 3 byte sequences only · mysql/mysql-server@43a506c文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

这个事情我查不到任何前因后果,查不到任何的文章,讨论和相关资料。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

但大致猜测就是,MySQL当时又想用定长的存储,又觉得太浪费,干脆一鼓作气,把6改成了3。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

在Unicode中,3个Byte可以支持所有的BMP(basic multi-lingual plane)的字符;但是无法支持SMP(supplementary multi-lingual plane),包括emoji(这是重灾区),一些生僻的CJK字符,一部分生僻的符号等。对于主要的文字(英文、欧洲各种语种、中文、日文……),3个byte的utf8也算是够用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

但是,多年之后,也许是苹果强力推emoji,大家才发现MySQL的utf8其实并不那么utf8。直到2010年,MySQL的5.5.3版本的时候,才引入了utf8mb4(从此刻开始,utf8是“utf8mb3“的alias)。这个change非常的不起眼,在更新总体介绍时压根就没提,只在明细里写了一行。也许是因为6改3这个变更实在太过于傻缺,不想张扬?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

mysql 额外加入一个 utf8mb4 数据类型,而不是原地升级 utf8?

见:dev.mysql.com/doc/relno文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

本题问为啥不把utf8原地升级,这个非常容易理解。大量的数据库文件已经按照了utf8的格式存储。如果“原地升级”也就意味着,所有已经存在的数据库文件都要重建。数据这个东西~都懂得。如果MySQL真的这么干了,估计就不是会被骂,而是会直接被判死刑。用utf8mb4的形式慢慢过渡也算是可以理解的做法。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

顺便说一句。UTF8早期的标准RFC2279规定一个UTF8字符是1~6个Byte。这也是为什么早期Mysql把一个UTF8字符设计为6个Byte的原因。但是2003年11月,出了新的标准RFC3629,规定一个UTF8字符是1~4个Byte,就比MySQL做出那个很傻的commit晚了一年。历史真的很有趣。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

从2002年到2019年,已经17年过去了,MySQL 8.0刚刚GA不久,但是utf8依然是utf8mb3的别名。不知道什么时候这个在一个莫名其妙的决策下诞生的奇行种才会被完全干掉。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

哎~文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html

mysql 额外加入一个 utf8mb4 数据类型,而不是原地升级 utf8?
摘自MySQL8.0的文档
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/16690.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/sjk/16690.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定