MySQL不要再用utf8了

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL中真正的UTF-8不是utf8,而是utf8mb4

转载请注明出处❤️

作者:测试蔡坨坨

原文链接:caituotuo.top/6719361d.html


你好,我是测试蔡坨坨。

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

Bug回顾

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

INSERT INTO user_info ( user_id, user_name, emoji )
VALUES
    ( 1, '蔡坨坨', '🍌' );
AI 代码解读

原因分析

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

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

解决方案

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

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

字符字节

再插入一些数据:

INSERT INTO user_info ( user_id, user_name, emoji )
VALUES
    ( 2, '蔡坨坨', '🍌' ),
    ( 3, '蔡坨坨', '坨' ),
    ( 4, '蔡坨坨', '1' ),
    ( 5, '蔡坨坨', 'a' ),
    ( 6, '蔡坨坨', '*' );
AI 代码解读

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

SELECT * ,CHAR_LENGTH(emoji) as '字符' ,LENGTH(emoji) as '字节' FROM user_info;
AI 代码解读

如上图所示,这是将编码改成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。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
1
1
0
79
分享
相关文章
mysql中utf8、utf8mb4和utf8mb4_unicode_ci、utf8mb4_general_ci
mysql中utf8、utf8mb4和utf8mb4_unicode_ci、utf8mb4_general_ci
416 0
为什么不建议在MySQL中使用 utf8?
MySQL 字符编码集中有两套 UTF-8 编码实现:utf8 和 utf8mb4。 如果使用 utf8 的话,存储 emoji 符号和一些比较复杂的汉字、繁体字就会出错。
DataX:导入4字节UTF8编码(生僻字)到Mysql数据库的utf8mb4数据表
MySql数据库的编码支持UFT8字符集。utf-8编码可能是2个字节、3个字节、4个字节的字符,MYSQL的utf-8编码,只支持3个字节的字符。汉字中很多生僻字都是4个字节的字符,日常生活中人的姓名就会有很多高位的生僻字。
6390 0
【MySQL】init_connect='SET NAMES utf8',是干什么的?底层原理是什么?
【MySQL】init_connect='SET NAMES utf8',是干什么的?底层原理是什么?
962 0
为什么不建议在MySQL中使用 utf8 ?
为什么不建议在MySQL中使用 utf8 ?
159 0
为什么不建议在MySQL中使用 utf8 ?
【MySQL】character-set-server=utf8,是干什么的?底层原理是什么?
【MySQL】character-set-server=utf8,是干什么的?底层原理是什么?
830 0

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问