陈奇网络工作室

记住:千万不要在MySQL或MariaDB数据库中使用UTF-8

本文的内容

显示

1.

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

2.

MySQL数据库简史

3.

为什么这东西这么让人抓狂?

4.

摘要

4.1.

推荐阅读

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

MySQL简史

为什么这东西这么让人抓狂?

摘要

最近遇到一个bug。我试图通过Rails在MariaDB中保存一个用“utf8”编码的UTF-8字符串,然后出现了一个奇怪的错误:

不正确?字符串?值:\\xF0\\x9F\\x98\\x83?…'为了什么?专栏?总结?在哪里?划?一个

我用的是UTF-8编码的客户端,云服务器也是UTF-8编码的,云数据库也是。甚至要保存的字符串“…”也是合法的UTF-8。

问题的关键在于MySQL的“utf8”并不是真正的UTF-8。

“utf8”只支持每个字符最多三个字节,而真正的UTF-8是每个字符最多四个字节。

MySQL一直没有修复这个bug。2010年,他们发布了一个名为“utf8mb4”的字符集来绕过这个问题。

当然,他们并没有广泛宣传新字符集(可能是因为这个bug让他们很尴尬),以至于在网上仍然建议开发者使用“utf8”,但这些建议都是错误的。

简要概括如下:

MySQL的utf8mb4是真正的UTF-8。

MySQL的“utf8”是一种“独占编码”,只能对少数Unicode字符进行编码。

我想在这里澄清一下,所有正在使用utf8的MySQL和MariaDB用户都应该使用utf8mb4而不是utf8。

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

众所周知,计算机使用0和1来存储文本。例如,如果字符“c”被保存为“01000011”,那么计算机在显示该字符时需要经历两个步骤:

计算机读取“01000011”,得到数字67,因为67编码为“01000011”。

计算机在Unicode字符集中查找67,找到了“c”。

相同的:

我的计算机将Unicode字符集中的“c”映射到67。

我的电脑将67编码为“01000011”并发送到网络服务器。

几乎所有的网络应用程序都使用Unicode字符集,因为没有理由使用其他字符集。

Unicode字符集包含数百万个字符。最简单的编码是UTF-32,每个字符使用32位。这是最简单的方法,因为计算机一直把32位当成数字,计算机最擅长处理数字。但问题是,这是浪费空间。

UTF-8可以节省空间。在UTF-8中,字符“c”只需要8位,一些不常用的字符,如“”,需要32位。其他字符可能使用16位或24位。像这样的文章,如果使用UTF-8编码,只占UTF-32的四分之一。

MySQL的utf8字符集与其他程序不兼容,其所谓的“”可能真的是一坨.

MySQL数据库简史

为什么MySQL开发者会让“utf8”失效?我们或许可以从投稿日志中找到答案。

MySQL从4.1版本开始,也就是2003年开始支持UTF-8,今天使用的UTF-8标准(RFC 3629)出现的更晚。关注微信官方账号小黄鸭编程社区,回复关键词“手册”,获取最新编程手册。

旧的UTF-8标准(RFC 2279)支持每个字符最多6个字节。2002年3月28日,MySQL开发者在第一个MySQL 4.1预览版中使用了RFC 2279。

同年9月,他们对MySQL源代码做了一个调整:“UTF8现在最多只支持3字节序列”。

谁提交了这些代码?他为什么要这么做?这个问题不得而知。迁移到Git (BitKeeper原来是MySQL用的)后,MySQL代码库中很多提交者的名字都丢失了。没有任何线索可以解释2003年9月邮件列表中的这一变化。

但我可以试着猜一下。

2002年,MySQL做了一个决定:如果用户能够保证数据表的每一行都使用相同的字节数,那么MySQL就可以大大提高性能。为此,用户需要将文本列定义为“CHAR”,并且每个“CHAR”列的字符数总是相同的。如果插入的字符数少于定义的数,MySQL会填充后面的空格;如果插入的字符数超过定义的数目,超出的部分将被截断。

MySQL开发人员第一次尝试UTF时,每个字符使用6个字节——8,CHAR(1)使用6个字节,CHAR(2)使用12个字节,依此类推。

应该说他们最初的行为是正确的,可惜这个版本还没有发布。但它写在文件里,而且广为流传。所有了解UTF-8的人都同意文件中的内容。

但显然,MySQL开发者或厂商担心用户会做这两件事:

用CHAR定义列(目前CHAR是老古董了,不过那时候在MySQL用CHAR会更快,但是从2005年开始就不是这样了)。

将CHAR列的编码设置为“utf8”。

我的猜测是,MySQL开发人员想帮助那些想在空间和速度上取胜的用户,但是他们搞砸了“utf8”编码。

所以结果是没有赢家。那些希望空间和速度双赢的用户,在使用“utf8”的CHAR列时,实际上使用了比预期更多的空间和更慢的速度。希望正确的用户在使用“utf8”编码时,无法保存“”这样的字符。关注微信官方账号小黄鸭编程社区,回复关键词“手册”,获取最新编程手册。

这个非法字符集发布后,MySQL无法修复,因为这需要所有用户重建数据库。最后,MySQL在2010年重新发布了“utf8mb4”来支持真正的UTF-8。

为什么这东西这么让人抓狂?

因为这个问题,我疯狂了整整一周。我被utf8忽悠了,花了很长时间才发现这个bug。但我绝对不是唯一一个。网上几乎所有的文章都把“utf8”当成了真正的UTF-8。

“utf8”只能算是专有字符集,给我们带来了新的问题,但并没有得到解决。

摘要

如果你用的是MySQL或者MariaDB,不要用“utf8”编码,用“utf8mb4”代替。这里(https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4)提供了将现有数据库的字符编码从“utf8”更改为“utf8mb4”的指南。

英文原文:https://medium.com/@ Adam Hooper/in-MySQL-never-use-utf8-use-utf8mb 4-11761243 e434来源:infoq.cn/article/in-mysql-never-use-utf8-use-utf8.

转自小黄鸭编程社区

西部数码代理(chenqinet.cn)是工信部批准的正规老牌云服务商,拥有ISP、云牌照、IDC、CDN全业务资质。自成立以来,二十多年来一直专注于域名注册,虚拟主机,云服务器,企业邮箱,企业网站建立等互联网基础服务!

公司开发的云计算平台以便捷、高效、高性价比、意想不到的售后优势占领市场,跻身国内前三的接入服务商,为国内超过50万家网站提供高速稳定的托管服务!先后荣获中国高新技术企业、中国优秀云计算服务商、中国十大IDC企业、中国最受欢迎云服务商等称号!

目前西部数码代理高性能云服务器在售,最低仅售48元!

http://zhuji.chenqinet.cn/cloudhost/

后台-系统设置-扩展变量-手机广告位-内容页底部广告位3