MySQL不要再用utf8了

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
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, '蔡坨坨', '🍌' );

原因分析

在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, '蔡坨坨', '*' );

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

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。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
7月前
|
存储 关系型数据库 MySQL
Mysql中utf8和utf8mb4区别
Mysql中utf8和utf8mb4区别
102 0
|
6月前
|
存储 自然语言处理 搜索推荐
mysql中utf8、utf8mb4和utf8mb4_unicode_ci、utf8mb4_general_ci
mysql中utf8、utf8mb4和utf8mb4_unicode_ci、utf8mb4_general_ci
168 0
|
7月前
|
存储 关系型数据库 MySQL
为什么不建议在MySQL中使用 utf8?
MySQL 字符编码集中有两套 UTF-8 编码实现:utf8 和 utf8mb4。 如果使用 utf8 的话,存储 emoji 符号和一些比较复杂的汉字、繁体字就会出错。
|
关系型数据库 MySQL Linux
mysql 8中utf8和utf8mb4运行时的编码警告提醒[Warning]——my.ini配置问题
mysql 8中utf8和utf8mb4运行时的编码警告提醒[Warning]——my.ini配置问题
|
存储 关系型数据库 MySQL
Mysql中utf8和utf8mb4区别
Mysql中utf8和utf8mb4区别
136 0
|
SQL 存储 关系型数据库
【MySQL】init_connect='SET NAMES utf8',是干什么的?底层原理是什么?
【MySQL】init_connect='SET NAMES utf8',是干什么的?底层原理是什么?
867 0
|
存储 Dubbo NoSQL
为什么不建议在MySQL中使用 utf8 ?
为什么不建议在MySQL中使用 utf8 ?
128 0
为什么不建议在MySQL中使用 utf8 ?
|
存储 关系型数据库 MySQL
DataX:导入4字节UTF8编码(生僻字)到Mysql数据库的utf8mb4数据表
MySql数据库的编码支持UFT8字符集。utf-8编码可能是2个字节、3个字节、4个字节的字符,MYSQL的utf-8编码,只支持3个字节的字符。汉字中很多生僻字都是4个字节的字符,日常生活中人的姓名就会有很多高位的生僻字。
6013 0
|
存储 关系型数据库 MySQL
【MySQL】character-set-server=utf8,是干什么的?底层原理是什么?
【MySQL】character-set-server=utf8,是干什么的?底层原理是什么?
628 0
|
关系型数据库 MySQL
mysql编码问题——charset=utf8你真的弄明白了吗?(三)
mysql编码问题——charset=utf8你真的弄明白了吗?(三)
mysql编码问题——charset=utf8你真的弄明白了吗?(三)