最近遇到一个神奇的问题,在往数据库中插入聊天表情的时候,离奇的报错,我的客户端、服务器、数据库都是UTF-8 编码的,所以应该不会出现问题。最终发现根本的原因在于MySQL 的“utf8”实际上不是真正的 UTF-8。

Mysql的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”。

产生问题的历史原因

为什么 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 定义列(在现在看来,CHAR 已经是老古董了,但在那时,在 MySQL 中使用 CHAR 会更快,不过从 2005 年以后就不是这样子了)。
(2)将 CHAR 列的编码设置为“utf8”。
我的猜测是 MySQL 开发者本来想帮助那些希望在空间和速度上双赢的用户,但他们搞砸了“utf8”编码。
所以结果就是没有赢家。那些希望在空间和速度上双赢的用户,当他们在使用“utf8”的 CHAR 列时,实际上使用的空间比预期的更大,速度也比预期的慢。而想要正确性的用户,当他们使用“utf8”编码时,却无法保存像“”这样的字符。
在这个不合法的字符集发布了之后,MySQL 就无法修复它,因为这样需要要求所有用户重新构建他们的数据库。最终,MySQL 在 2010 年重新发布了“utf8mb4”来支持真正的 UTF-8。

Mysql中的utf-8竟然是假的!相关推荐

  1. mysql 中的 utf_Mysql中的utf-8竟然是假的!

    最近遇到一个神奇的问题,在往数据库中插入聊天表情的时候,离奇的报错,我的客户端.服务器.数据库都是UTF-8 编码的,所以应该不会出现问题.最终发现根本的原因在于MySQL 的"utf8&q ...

  2. php mysql utf 8_PHP+MySQL中对UTF-8,UTF8(utf8),set names gbk 的理解

    问题一:在我们进行数据库操作时会发现,数据库中表的编码用的是utf-8,但是在进行dos命令是要使用set names gbk (一)Mysql中默认字符集设置有四级:服务器级,数据库级,表级,和字段 ...

  3. mysql utf 8bm4 没用_不要在 MySQL 中使用“utf8”,請使用“utf8mb4”

    不要在 MySQL 中使用"utf8",請使用"utf8mb4" 最近我遇到了一個bug,我試着通過Rails在以"utf8"編碼的Mari ...

  4. 浅谈MySQL中utf8和utf8mb4的区别

    一.什么是UTF8MB4? 我们在使用PhpMyAdmin管理面板时,可以在首页看到名为"Server connection collation"(服务器连接排序规则)的选项,用来 ...

  5. mysql中正则表达式的用法_Mysql中正则表达式Regexp常见用法

    Mysql中Regexp常见用法 模糊匹配,包含特定字符串 # 查找content字段中包含"车友俱乐部"的记录 select * from club_content where ...

  6. 求求你,别在 MySQL 中使用 UTF-8了!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来源:blog.csdn.net/qq_39390545/ ...

  7. 为什么不建议在 MySQL 中使用 UTF-8?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 _陈哈哈|https://sourl.cn/kKbzpH 记得去年 ...

  8. 记住:永远不要在 MySQL 中使用 UTF-8

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:http://t.cn/EIhnOJT 最近我遇到了一个 b ...

  9. 漫话:如何给女朋友解释为什么不能在 MySQL 中使用 UTF-8 编码

    作者 | 漫话编程 来源 | 漫话编程(ID:mhcoding) MySQL是一种关系型数据库,这个大家肯定都不陌生,使用MySQL创建数据库的时候,大家需要指定一种编码方式. 很多时候,大家基于自己 ...

最新文章

  1. 用 WEKA 进行数据挖掘,第 2 部分: 分类和群集
  2. 点击下载!《阿里云SRE技术期刊》2021年5月刊发布啦!
  3. AbstractQueuedSynchronizer源码解析
  4. 轻量级 Java Web 框架技术选型
  5. setScaledContents的看法
  6. 传百度无人车计划分拆,百度回复:不实信息,目前未有分拆计划
  7. es6 Class简介
  8. 还在为运维烦恼?体验云上运维服务,提意见赢好礼!【华为云分享】
  9. java占位符填充_程序员:深入理解Java虚拟机,对象的内存布局
  10. LSTM及其改进用于视觉任务中
  11. JAVA面试--电商业内大厂
  12. CVE-2016-1240 Tomcat 服务本地提权漏洞
  13. Discuz!NT 系统架构分析(以前的)
  14. 《Go程序设计语言》- 第10章:包和go工具
  15. 从百度指数到微信指数,我们正进入“数据世界”
  16. 跟父母还是要保持一定的距离感
  17. 电网企业 财务管理创新
  18. 像素(px)与厘米的关系
  19. Java 必会的工具库,让你的代码量减少90%
  20. VS2015安装完成后Visual C++的一些模板找不到,安装C++新模板

热门文章

  1. python声明_在Python中什么是全局声明?
  2. 山东外贸职业学院王彩霞老师网上考试系统及c语言考试题库》,2019年山东外贸职业学院单独招生考试 《语文》考试大纲(夏季高考)...
  3. 硬中断 / 软中断的原理和实现
  4. 大班运用计算机教学案例,幼儿园大班体验课程教学案例
  5. 3MIN干完一周的工作量?快来看看应该如何部署 Kubernetes!
  6. Spring Cloud 2020.0.5 发布
  7. 皮一皮:男女的不同...
  8. 皮一皮:好一道举世佳酿“青山卧雪龙”...
  9. 为什么我使用了索引,查询还是慢?
  10. Spring Cloud Config Server迁移节点或容器化带来的问题