企业建站Mysql为什么不能用“UFT8”
  • 更新时间:2024-05-19 12:12:20
  • 网站建设
  • 发布时间:11个月前
  • 364

我在使用MYSQL的时候经常遇到一个问题,试图通过Rails将一个UTF-8编码的UTF-8字符串保存到MariaDB中,然后出现了一个特别奇怪的错误:

第1 行“摘要”列的字符串值不正确: ‘\xF0\x9F\x98\x83 …’

UTF-8编码的客户端,服务器端也是UTF-8编码的,数据库也是。就连要保存的字符串“.”也是合法的UTF-8。问题的症结在于MySQL 的“utf8”实际上并不是真正的UTF-8。 “utf8”仅支持每个字符最多三个字节,而真正的UTF-8 每个字符最多四个字节。原来MySQL一直没有修复这个bug。他们在2010 年发布了一个名为“utf8mb4”的字符集来绕过这个问题。他们没有为这个新的字符集做广告,所以网上仍然建议开发者使用“utf8”,但这些建议都是错误的。

简要总结如下:

(1) MySQL的“utf8mb4”才是真正的“UTF-8”。

(2) MySQL的“utf8”只是一种“专有编码”,它能编码的Unicode字符并不多。

小编在这里建议使用“utf8”的MySQL和MariaDB的用户换成“utf8mb4”,不要再使用“utf8”了。

首先,什么是编码?什么是UTF-8?

众所周知,计算机存储的本质是二进制,即用0和1来存储文本。例如,字符“C”存储为“01000011”,那么计算机在显示这个字符时需要经过两个步骤:

我的电脑会ldq

uo;C”映射成 Unicode 字符集中的 67。
  • 我的电脑将 67 编码成“01000011”,并发送给 Web 服务器。

  • 相对的:

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

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

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

    Unicode 字符集包含了上百万个字符。最简单的编码是 UTF-32,每个字符使用 32 位。这样做最简单,因为一直以来,计算机将 32 位视为数字,而计算机最在行的就是处理数字。但问题是,这样太浪费空间了。

    UTF-8 可以节省空间,在 UTF-8 中,字符“C”只需要 8 位,其他的字符可能使用 16 位或 24 位。一篇类似本文这样的文章,如果使用 UTF-8 编码,占用的空间只有 UTF-32 的四分之一左右。

    第二、   MySQL 简史

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

    MySQL 4.1 版本支持 UTF-8,也就是 2003 年,而今天使用的 UTF-8 标准(RFC 3629)是随后才出现的。而旧版的 UTF-8 标准(RFC 2279)最多支持每个字符 6 个字节。2002 年 3 月 28 日,MySQL 开发者在第一个 MySQL 4.1 预览版中使用了 RFC 2279。同年 9 月,他们对 MySQL 源代码进行了一次调整:“UTF8 现在最多只支持 3 个字节的序列”。那么是谁提交了这些代码?他为什么要这样做?这个问题不得而知。在迁移到 Git 后(MySQL 最开始使用的是 BitKeeper),MySQL 代码库中的很多提交者的名字都丢失了。2003 年 9 月的邮件列表中也找不到可以解释这一变更的线索。

    不过可以试着猜测一下。

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

    MySQL 开发者在最开始尝试 UTF-8 时使用了每个字符 6 个字节,CHAR(1) 使用 6 个字节,CHAR(2) 使用 12 个字节,并以此类推。

    可以说,他们最初的版本才是正确的,可惜这一版本一直没有发布。但是文档上却写了,而且广为流传,所有了解 UTF-8 的人都认同文档里写的东西。

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

    1. 使用 CHAR 定义列。

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

    小编猜测应该是 MySQL 开发者本来想帮助那些希望在空间和速度上双赢的用户,但时他们却搞砸了“utf8”编码。

    所以结果就是失败的。那些希望在空间和速度上双赢的用户,当他们在使用“utf8”的 CHAR 列时,实际上使用的空间比预期的更大,速度也比预期的慢。而想要正确性的用户,当他们使用“utf8”编码时,却无法保存像“”这样的字符。

    第三、为什么这个问题很引起人们的注意

    关于这个问题,小编曾经花费很多时间才找到这个 bug。但是不确定这是唯一的一个,网络上几乎所有的文章都把“utf8”当成是真正的 UTF-8。“utf8”只能算是个专有的字符集,它给我们带来了新问题,却一直没有得到解决。

    我们专注高端建站,小程序开发、软件系统定制开发、BUG修复、物联网开发、各类API接口对接开发等。十余年开发经验,每一个项目承诺做到满意为止,多一次对比,一定让您多一份收获!

    本文章出于推来客官网,转载请表明原文地址:https://www.tlkjt.com/web/11472.html

    在线客服

    扫码联系客服

    3985758

    回到顶部