MySQL 数据库字符集 utf8 和 utf8mb4 的区别
参考于今日头条上Java芋道源码的-----记住:永远不要在 MySQL 中使用 UTF-8
字符集选择

MySQL 的 utf8 实际上不是真正的 UTF-8。utf8 只支持每个字符最多三个字节,而真正的 UTF-8 是每个字符最多四个字节。
MySQL 一直没有修复这个 bug,他们在 2010 年发布了一个叫作 utf8mb4 的字符集,绕过了这个问题。当然,他们并没有对新的字符集广而告之(可能是因为这个 bug 让他们觉得很尴尬),以致于现在网络上仍然在建议开发者使用 utf8,但这些建议都是错误的。
简单概括如下:
(1)MySQL 的 utf8mb4 是真正的 UTF-8。
(2)MySQL 的 utf8 是一种专属的编码,它能够编码的 Unicode 字符并不多。
所有在使用 utf8 的 MySQL 和 MariaDB 用户都应该改用 utf8mb4,永远都不要再使用 utf8。
这里(https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4)提供了一个指南用于将现有数据库的字符编码从 utf8 转成 utf8mb4。
历史原因
为什么 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 数据库字符集 utf8 和 utf8mb4 的区别的更多相关文章
- mysql字符集 utf8 和utf8mb4 的区别
一.导读我们新建mysql数据库的时候,需要指定数据库的字符集,一般我们都是选择utf8这个字符集,但是还会又一个utf8mb4这个字符集,好像和utf8有联系,今天就来解析一下这两者的区别. 二.起 ...
- linux下设置mysql数据库字符集utf8
mysql中文乱码解决方法:将mysql数据库编码统一utf8 查看数据库编码: show variables like 'character%'; 编辑/etc/my.cnf [mysql] def ...
- inux下设置mysql数据库字符集utf8
mysql中文乱码解决方法:将mysql数据库编码统一utf8 查看数据库编码: ? 1 <span style="font-size: 16px;"><stro ...
- mysql字符集utf8和utf8mb4区别
1.起因 公司游戏项目上线第一天,出现单个区服异常宕机的问题,根据日志排查下来,连接数据的时候报错,后面排查是因为有玩家插入Emoji 等表情导致无法存储如数据库,数据库字符集编码为utf8,后续改成 ...
- MySQL中 utf8与utf8mb4的区别
MySQL中 utf8与utf8mb4的区别 一.简介 MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode.好在 ...
- 【记录】mysql中建表utf8和utf8mb4区别?timestamp和datetime区别?
mysql中建表utf8和utf8mb4区别? 1:utf8 是 Mysql 中的一种字符集,只支持最长三个字节的 UTF-8字符,也就是 Unicode 中的基本多文本平面 2:要在 Mysql 中 ...
- 查看和设置MySQL数据库字符集(转)
查看和设置MySQL数据库字符集作者:scorpio 2008-01-21 10:05:17 标签: 杂谈 Liunx下修改MySQL字符集:1.查找MySQL的cnf文件的位置find / -ina ...
- 使用SQL语句修改Mysql数据库字符集的方法
使用SQL语句修改Mysql数据库字符集的方法 修改库: alter database [$database] character set [$character_set] collate [$c ...
- MySQL数据库之MyISAM与InnoDB的区别
MySQL数据库之MyISAM与InnoDB的区别 从以下几个方面: 1.存储结构 每个MyISAM在磁盘上存储成三个文件.第一个文件的名字以表的名字开始,扩展名指出文件类型. .frm文件存储表定义 ...
随机推荐
- meta 标签知识汇总
概要 标签提供关于HTML文档的元数据.元数据不会显示在页面上,但是对于机器是可读的.它可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 web 服务. -- W3School ...
- Python测试远程端口连接时间
问题 最近自己服务器访问别人的服务器,有时候会报超时错误,有时候又能够正常访问别人服务器. 思路 最开始猜测是网络不稳定造成的,但是自己没有收集什么时候超时,什么时候能正常访问别人服务器的日志,搞网络 ...
- Python 简单实现数学四则运算
GitHub地址:https://github.com/compassblog/PythonExercise 一.题目描述 (1)能自动生成小学四则运算题目: (2)能支持真分数的四则运算: 二.实现 ...
- 如何更好的编写async函数
2018年已经到了5月份,node的4.x版本也已经停止了维护 我司的某个服务也已经切到了8.x,目前正在做koa2.x的迁移 将之前的generator全部替换为async 但是,在替换的过程中,发 ...
- 从 源码 谈谈 redux compose
compose,英文意思 组成,构成. 它的作用也是通过一系列的骚操作,实现任意的.多种的.不同的功能模块的组合,用来加强组件. 看看源码 https://github.com/reactjs/red ...
- 关于easyui Datagrid一些样式记录
此篇文章主要记录在使用datagrid中常见的修改样式方式以及样式效果配图!!!! 一丶存在选中框的时候标题栏合并显示序号字段. 代码展示: onLoadSuccess: function (data ...
- Android 样式的开发(转)
Android(2) 目录(?)[-] rectangle oval line ring layer-list篇 普通图片 bitmap标签 点九图片 nine-patch标签 color标签 ...
- “史上更难就业季”暴露出啥隐情?
如果说,2013年中国高校毕业生达到699万,被称为"史上最难就业季".那么2014年将成为去年之后的"更难就业季".据最新资料显示,2014年应届大学毕业 ...
- HTML和CSS前端基础
Html标题 <h1>这是一级标题</h1> <h2>这是二级标题</h2> <h3>这是三级标题</h3> Html段落.换行 ...
- jenkins+gitlab自动化编译部署方案探索及服务端编译webpack实战
一. 背景 之前我们的开发流程为在本地进行webpack打包编译,然后svn提交源代码和编译后的代码.同时每次提交前也会从svn更新源代码和编译后的代码.这样做有几个缺点: 1. svn 更新和提交编 ...