iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >为什么永远不要在MySQL中使用UTF-8
  • 182
分享到

为什么永远不要在MySQL中使用UTF-8

2023-06-19 11:06:32 182人浏览 独家记忆
摘要

这篇文章给大家介绍为什么永远不要在MySQL中使用UTF-8,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。最近我遇到了一个bug,我试着通过Rails在以“utf8”编码的MariaDB中保存一个UTF-8字符串,然后

这篇文章给大家介绍为什么永远不要在MySQL中使用UTF-8,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

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

Incorrectstring value:‘\xF0\x9F\x98\x83 <…’ for column ‘summary’ at row 1

我用的是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”。

同样的:

我的电脑将“C”映射成Unicode字符集中的67。

我的电脑将67编码成“01000011”,并发送给WEB服务器

几乎所有的网络应用都使用了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版本开始支持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开发者或厂商担心会有用户做这两件事:

使用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”。

关于为什么永远不要在MySQL中使用UTF-8就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

您可能感兴趣的文档:

--结束END--

本文标题: 为什么永远不要在MySQL中使用UTF-8

本文链接: https://www.lsjlt.com/news/295776.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 为什么永远不要在MySQL中使用UTF-8
    这篇文章给大家介绍为什么永远不要在MySQL中使用UTF-8,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。最近我遇到了一个bug,我试着通过Rails在以“utf8”编码的MariaDB中保存一个UTF-8字符串,然后...
    99+
    2023-06-19
  • 为什么不建议在 MySQL 中使用 UTF-8?
    最近我遇到了一个bug,我试着通过Rails在以“utf8”编码的MariaDB中保存一个UTF-8字符串,然后出现了一个离奇的错误:Incorrect string value:&nb...
    99+
    2024-04-02
  • 为何不要在MySQL中使用UTF-8编码方式详解
    MySQL的UTF-8编码方式 MySQL 从 4.1 版本开始支持 UTF-8,也就是 2003 年,然而目前流行的UTF-8 标准(RFC 3629)是在此之后规定的。正因此,才造就了MySQL中的U...
    99+
    2024-04-02
  • 永远不要在 MySQL 中使用 utf8,使用 utf8mb4 作为代替
    今天的错误:我试图在 MariaDB 「utf8」 编码的数据库中存储一个 UTF-8 字符串,Rails 出现了一个奇怪的错误:Incorrect string value: ‘\xF0\x9F\x98\x8...
    99+
    2022-11-16
    utf8mb4 mysql
  • 为什么要使用MySQL
    这篇文章给大家分享的是有关为什么要使用MySQL的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。什么是MySQL  MySQL原本是一个开放源码的关系数据库管理系统,原开发者为瑞典...
    99+
    2024-04-02
  • 为什么不要在 Flutter 中使用全局变量
    目录前言Flutter 中的全局变量是什么?Flutter 中使用全局变量的缺点1. 复杂的代码维护过程2. 全局变量使单元测试变得痛苦3. 全局变量导致“面条&rdqu...
    99+
    2024-04-02
  • MySQL中为什么要使用索引
    小编给大家分享一下MySQL中为什么要使用索引,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!索引是什么?MySQL 官方对索引的...
    99+
    2024-04-02
  • User这个词为什么不要在代码中使用
    今天给大家介绍一下User这个词为什么不要在代码中使用。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。当你意识到你在项目开始时做的轻量、简单的设想竟然完全错了时...
    99+
    2023-06-28
  • 为什么在MySQL中几乎不使用分区表
    这篇文章主要介绍“为什么在MySQL中几乎不使用分区表”,在日常操作中,相信很多人在为什么在MySQL中几乎不使用分区表问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”为什么在...
    99+
    2024-04-02
  • 为什么不需要在JavaScript使用switch 语句!
    本篇文章为大家展示了为什么不需要在JavaScript使用switch 语句!,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。没有 switch 就没有复杂的代码块s...
    99+
    2024-04-02
  • 为什么要在Ruby APP中使用Neo4j
    为什么要在Ruby APP中使用Neo4j,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。每天,我都需要储存大量的数据,而我可以使用很多工具,比如 Postgre...
    99+
    2023-06-17
  • 为什么要停止在JavaScript中使用类
    为什么要停止在JavaScript中使用类,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。多年来,OOP(面向对象编程)是软件工程中的事实上的标...
    99+
    2024-04-02
  • 在Activity中为什么要用managedQuery()
    在Activity中使用managedQuery()方法是为了在Android 3.0(API级别11)之前的版本中访问Conten...
    99+
    2023-09-01
    Activity
  • 为什么要在LeetCode中使用Python的NumPy库?
    近年来,人工智能和机器学习的兴起,让编程语言的选择变得更加重要。在算法和数据结构领域,LeetCode已经成为了一个非常受欢迎的学习平台,许多程序员在这里刷题、学习和交流。而在这个过程中,Python的NumPy库也成为了许多程序员喜爱的选...
    99+
    2023-06-22
    numy leetcode 文件
  • 为什么不要PySnoope中使用print进行调试
    为什么不要PySnoope中使用print进行调试?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。PySnooper 是一个非常方便的调试器。如果您正在试图弄清楚为什么您的Pyt...
    99+
    2023-06-06
  • 为什么不要在using语句中调用WCF服务
    这篇文章主要介绍为什么不要在using语句中调用WCF服务,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!如果你调用WCF服务时,像下面的代码这样在using语句中进行调用,需要注意一个问题。using (C...
    99+
    2023-06-17
  • 在MySQL中为何不建议使用utf8
    目录何为字符集?有哪些常见的字符集?ASCIIGB2312GBKGB18030BIG5Unicode & UTF-8 编码mysql 字符集MySQL 字符编码集中有两套 UTF-8 编码实现:utf8 和 ut...
    99+
    2024-04-02
  • 为什么不在Python中使用无用分号
    这篇文章主要介绍“为什么不在Python中使用无用分号”,在日常操作中,相信很多人在为什么不在Python中使用无用分号问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”为什么不在Python中使用无用分号”的疑...
    99+
    2023-06-16
  • 为什么mysql字段要使用NOT NULL
    最近刚入职新公司,发现数据库设计有点小问题,数据库字段很多没有NOT NULL,对于强迫症晚期患者来说,简直难以忍受,因此有了这篇文章。 基于目前大部分的开发现状来说,我们都会把字段...
    99+
    2024-04-02
  • 为什么要在 PHP shell 中使用缓存路径?
    PHP shell 是 PHP 编程语言的一个交互式环境,它可以让我们在命令行中直接执行 PHP 代码。在实际的开发中,我们经常需要在 PHP shell 中测试一些代码,以验证其正确性或者快速地尝试一些新的语法特性。然而,PHP shel...
    99+
    2023-06-26
    shell 缓存 path
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作