前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >MySQL不要再用utf8了

MySQL不要再用utf8了

作者头像
测试蔡坨坨
发布于 2022-12-21 13:12:46
发布于 2022-12-21 13:12:46
2.1K00
代码可运行
举报
运行总次数:0
代码可运行

“阅读本文大概需要3分钟。

你好,我是测试蔡坨坨。

前些日碰到一个因MySQL数据库编码问题导致的Bug,在此记录,供小伙伴参考。

Bug回顾

原本是一句再普通不过的INSERT语句,但是由于VALUE中含有emoji文字,导致执行SQL语句时报错。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
INSERT INTO user_info ( user_id, user_name, emoji )
VALUES
 ( 1, '蔡坨坨', '🍌' );

原因分析

MySQL数据库中,utf8编码只支持每个字符最多3个字节,而真正的UTF-8每个字符最多支持4个字节。

由于emoji符号、一些较复杂的文字、繁体字、中日韩超大字符集里面的汉字都是占4个字节,所以导致写入失败。

解决方案

修改数据库编码、系统编码以及表字段的编码格式为utf8mb4:

修改之后再次执行SQL语句,就可以执行成功了:

字符字节

再插入一些数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
INSERT INTO user_info ( user_id, user_name, emoji )
VALUES
 ( 2, '蔡坨坨', '🍌' ),
 ( 3, '蔡坨坨', '坨' ),
 ( 4, '蔡坨坨', '1' ),
 ( 5, '蔡坨坨', 'a' ),
 ( 6, '蔡坨坨', '*' );

通过以下SQL语句可以清晰对比以下所占的字符数和字节数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT * ,CHAR_LENGTH(emoji) as '字符' ,LENGTH(emoji) as '字节' FROM user_info;

如上图所示,这是将编码改成utf8mb4之后插入的数据,其中数字、英文字母、特殊符号占1个字节,中文占3个字节,但emoji符号占4个字节,所以导致写入失败,应该改成utf8mb4。

MySQL的Bug

这个问题本质上是MySQL一直没有修复的Bug,官方在2010年发布了一个叫utf8mb4的字符集,从而巧妙地绕开这个问题。但是,他们并没有对新的字符集utf8mb4广而告之,可能是因为这个Bug让他们很尴尬,以至于很多人都还默认使用utf8,并且现在网络仍然建议开发者使用utf8,这些建议其实是错误的。

utf8mb4才是真正的UTF-8

没错,MySQL中的utf8mb4才是真正的UTF-8,MySQL中的utf8其实是一种专属的编码,它能编码的Unicode字符并不多。所有还在使用utf8编码格式的MySQL和MariaDB用户都应该改成utf8mb4,且不再使用utf8,避免出现类似的问题。

什么是编码

众所周知,计算机只认识0和1,使用0、1来存储文本的,比如:字母C会被存储为01000011,计算机在显示字母C时需要经历两个步骤,第一步计算机读取01000011,得到数字67,第二步计算机会在Unicode字符集中找到67所对应的字符C。同样,电脑会将字母C映射成Unicode字符集中的67,再将67编码成01000011发送给Web服务器。

为了方便传递信息,几乎所有的网络应用都会使用Unicode字符集,因为没有理由不使用它。

什么是UTF-8

Unicode字符集其实包含了上百万个字符,其中最简单的编码格式是UTF-32,因为每个字符都使用32位,但是这样做的缺点就是浪费空间。

在UTF-8中,字符C只需要8位,emoji符号需要32位,其他字符可能需要16位或者24位,因此UTF-8是可以变化长短的,这样做的好处就是可以更好地节省空间。

历史问题分析

为什么MySQL中的utf8不是真正的UTF-8?

或许从MySQL的更新日志中可以找到答案。

MySQL从2003年4.1版本开始支持UTF-8,而今天使用的UTF-8标准RFC3629是在此之后才出现的。

旧版的UTF-8标准RFC2279最多支持每个字符6个字节,MySQL开发者在2002年3月28日MySQL4.1预览版中使用了RFC2279标准。同年9月,官方对MySQL源码进行了调整,也就是一直沿用到现在最多支持3个字节的序列。具体为什么要这么做就不得而知了。

不过很显然,在这个不合法的字符集发布之后,MySQL就无法修复它,因为这样需要要求所有的用户重构他们的数据库,所以MySQL中utf8还是最多支持3个字节,最终,MySQL在2010年发布了utf8mb4来支持真正的UTF-8。

综上

相信很多同学还不知道这个知识点,主要是目前网络上大多数的文章教程都把MySQL中的utf8当成正真的UTF-8,因此希望看到这篇文章的小伙伴能有所收获并广而告之。所以大家以后在搭建MySQL、MariaDB数据库时,记得将数据库的编码格式设置为utf8mb4。

以上,完。

脚踏实地,仰望星空,和坨坨一起学习软件测试,升职加薪!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 测试蔡坨坨 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MySQL中的 utf8 并不是真正的UTF-8编码 ! !
改了数据库编码、系统编码以及表字段的编码格式 → utf8mb4 之后,就可以了:
陈哈哈
2020/07/03
8990
在MySQL中,不要使用“utf8”。使用“utf8mb4”
今天的错误:我试图将一个UTF-8字符串存储在MariaDB“utf8”编码的数据库中,并且引发了一个奇怪的错误:
银河1号
2019/05/16
1K0
SQL学习笔记之MySQL中真假“utf8” 问题
最近我遇到了一个 bug,我试着通过 Rails 在以“utf8”编码的 MariaDB 中保存一个 UTF-8 字符串,然后出现了一个离奇的错误:
Jetpropelledsnake21
2018/08/01
8830
为什么不建议在MySQL中使用 utf8 ?
MySQL 字符编码集中有两套 UTF-8 编码实现:utf8 和 utf8mb4。
Guide哥
2021/10/21
1.2K0
记住没:永远不要在 MySQL 中使用 UTF-8
简介 MySQL 的“utf8”实际上不是真正的 UTF-8。“utf8”只支持每个字符最多三个字节,而真正的 UTF-8 是每个字符最多四个字节。MySQL 一直没有修复这个 bug,他们在 2010 年发布了一个叫作“utf8mb4”的字符集,绕过了这个问题。当然,他们并没有对新的字符集广而告之(可能是因为这个 bug 让他们觉得很尴尬),以致于现在网络上仍然在建议开发者使用“utf8”,但这些建议都是错误的。
子润先生
2021/06/25
2890
MySQL中的utf8,真假?
究其原因,MySQL的"utf8"实际上不是真正的UTF-8。"utf8"只支持每个字符最多三个字节,而真正的UTF-8是每个字符最多四个字节。
bisal
2025/01/03
1040
MySQL中的utf8,真假?
微信小程序授权获取用户详细信息openid
Incorrect string value: ‘\xF0\x9F\x98\x83 <…’ for column ‘summary’ at row 1
李才哥
2019/07/10
5.7K0
微信小程序授权获取用户详细信息openid
相关推荐
MySQL中的 utf8 并不是真正的UTF-8编码 ! !
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档