前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >五分钟教你彻底解决MySQL中文乱码

五分钟教你彻底解决MySQL中文乱码

作者头像
公众号 云舒编程
发布2024-01-31 10:45:43
2640
发布2024-01-31 10:45:43
举报
文章被收录于专栏:图解系列图解系列

突发状况

周末,当我在峡谷马上拿下五杀时,突然手机弹出消息。

"线上系统的评论功能不能用了"。

还没等我反应过来,一个视频会议电话已经打进来了。作为社畜只能默默放下手机,打开电脑接入会议。

刚进入会议,产品疯狂吐槽。

"刚给用户开通灰度,用户怎么就用不了";

"重试好几次都不行";

"每次发表情都不行";

听到这,有经验的研发兄弟应该大概猜出来了,跟数据库的字符集有关系。

于是迅速登录mysql,查询了评论表的字符集,发现是utf8。于是马上提单修改字符集为utf8mb4。问题马上解决了。

代码语言:javascript
复制
alter table `table_name` modify clo_name varchar(20) character set utf8mb4;

utf8 其实是 utf8mb3 的别名,只使用 1~3 个字节表示字符。 utf8mb4 使用 1~4 个字节表示字符,能够存储更多的 emoji 表情及任何新增的 Unicode 字符。utf8mb4 兼容 utf8 ,且比 utf8 能表示更多的字符,是 utf8 字符集的超集。所以现在一些新的业务建议将数据库的字符集设置为 utf8mb4 ,特别是有表情存储需求时。 正是因为utf8mb4兼容utf8,所以可以直接改。如果是其他字符集就不能直接改了。

复盘

维护的这个评论系统非常的老,前端支持的编辑器也很老,原本只支持纯文本格式,所以之前一直相安无事。但是上周老大提了个需求,让前端支持富文本编辑器。但是前端哥们没有跟我沟通,我也忘记查评论表字段的字符集了,导致了一个低级问题。

本来事情到这就结束了,但是聪明的我仔细想了下,明明存到计算机里都是0和1,为啥会报错呢?

要解释这个问题,我们还得从字符集编码这个话题开始聊起。

我们知道对于计算机而言,所有的数据都是以0和1的形式存储在磁盘中的,包括在网络上进行传输的信息都需要变为0和1再进行传输。

也就是需要一个机制 把人的语言变为计算机的语言,我们称之为编码。

同样的需要一个机制 把计算机的语言变为人的语言,我们称之为解码。

上面两个场景结合起来,统称为字符编码。

那我们平常总是遇到的乱码是什么情况呢?

那就是同一份数据的编码方和解码方使用的规则不一样导致的。

比如下面这样的编解码就容易友尽。

一、ASCII码

既然有了通信的需求,那么就需要指定一套规则。只要大家都遵循这套规则,就万事大吉了,不会鸡同鸭讲了。完美实现同一个世界同一个梦想。

最开始,美国制定了一套字符编码,叫ASCII码,一共规定了128个字符。只需要7位(bit)就可以一一映射。但是一般采用一个字节(8 bit)进行存储编码,最高位统一为0。

比如我们必会的ping对应的编码就是:\u0070\u0069\u006e\u0067 (16进制表示,2进制太长了)

具体的映射规则可以到ASCII码对照表查看。

对于母语是英语的国家ASCII码是完全够用了。但是随着计算机的普及,越来越多的国家加入互联网。那么对于这些国家ASCII码肯定是不够用的。

比如中国,汉字就多达10万左右。ASCII码只使用8个字节进行表示,最多可以表示256个字符,还不够塞牙缝,肯定是不够用的。于是对于汉字就提出了GB2312 编码方式,即使用两个字节表示一个汉字,那么就可以表示 256 * 256 = 65536 个字符。

汉字提出了GB2312编码,那韩文呢,日文呢,泰文呢。世界上那么多国家那么多语言,如果每一个人都提出自己的编码方式,那计算机就得装载各种编码程序,这将极其复杂,也增加了出错的几率。

想想你好不容易下载的日本电影被编解码程序解析为了新闻联播时。

二、大一统-Unicode

正所谓天下大势分久必合,合久必分,咳咳咳。

正式因为世界上存在太多的编码方式,一段0101010的二进制数字可以被解释为不同的语义。

因此对沟通上带来了极大的成本。

像上学的时候,看小说还是使用的txt,就总是容易出现乱码。

一般故事发展到这个时候,就会出现一本秘籍统一江湖,这就是Unicode编码。

unicode的思路很简单,你们不是国家多,语言多吗?行,我给世界上的每个字符都分配一个编号。

具体的字符映射表可以到 unicode映射表进行查询。

目前的序号的范围从0×000000到0x10FFFF,一共表示了110多万个字符。

不过这样的编码方式也带来了问题,对于单个英文字符,也需要三个字节进行编码,造成了极大的浪费。要知道互联网每天产生的数据可以绕地球好几圈,如果这么浪费的进行存储,只能说一句:土豪带带我。

故事发展到这个时候,就会出现一本秘籍统一江湖。

三、UTF-8

由于互联网的高度普及,提出一种可行的高效的的编码方式迫在眉睫。

于是基于Unicode的编码方式UTF-8横空出世。

UTF-8并不是一种新的编码协议,他是Unicode编码的一种实现,类似的还有UTF-16,UTF-32。这是由于Unicode只是提出了一套映射规范,但是关于怎么存储,怎么提高效率都没有提及。所以才出现了UTF-8

我们知道按照原始的 Unicode 规定的存储,对于低位字符会操作极大的空间浪费。UTF-8提出了变长编码的思路。诶,你不是低位字符浪费吗,那我就用少一点的字节进行表示。

UTF-8 使用1~4个字符表示一个符号,根据符号的Unicode码而变化字节长度。

具体规则如下:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此UTF-8 编码是兼容ASCII的。

2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的二进制位,全部为这个符号的 Unicode 码。

\

那么问题来,计算机怎么知道什么是单字节,什么是n字节。对他不就是010101吗?

别慌,UTF-8 对于专门定义了一张转化表进行了解释:

Unicode符号范围(16进制表示)

Unicode符号范围(10进制表示)

utf-8编码(二进制表示)

0000 0000 ---- 0000 007F

0---127

0xxxxxxx

0000 0080 ---- 0000 07FF

128---2047

110xxxxx 10xxxxxx

0000 0800 ---- 0000 FFFF

2048---65535

1110xxxx 10xxxxxx 10xxxxxx

0001 000 ---- 0010 FFFF

65536---131071

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

刚看到这张表,大家肯定一头雾水,别慌。我们举例实战推演帮助大家理解。

比如现在需要编码汉字"中",首先需要找到"中"Unicode编码。"中"Unicode编码是:4E2D(16进制)--> 20013(10进制)。可以发现落在了上表的

2048---65535 区间。也就是"中"对应的utf-8 编码为

1110xxxx 10xxxxxx 10xxxxxx。

第一步完成了,找到了模板,剩下就是填充xxx了。

把4E2D 转为 二进制 得到 100111000101101。

按照从后往前填充,不足补0的规制,把得到的二进制填充到utf-8模板中可得:11100100 10111000 10101101,这就是"中"经过utf-8编码后的结果。

正向编码理解了,那把0和1字符串变为字符就简单了。

首先按顺序读取,如果第一位是0,那证明是单字符,直接取一个字节去掉头部得到一个数字,去Unicode表中找对应的字符。

如果第一位是1,那就继续往后读,指定读到0为止。这个时候读到几个1就证明需要几个字节进行编码。例如"中"的二进制可以知道需要三个字节,所以这里取三个字节,分别去掉第一个字节的三个1,后面两个字节的10,得到一个数字,直接去Unicode表里找到对应字符。

四、大功已成

相信学到这里,你已经完全掌握了编码的真谛,下次再遇到日本电影变成新闻联播时也可以从容应对了。

五、扩展

通过下面的命令可以查询当前mysql支持的字符集。

代码语言:javascript
复制
SHOW CHARACTER SET;

这是我安装的mysql(8.0.29)支持的字符集。

虽然mysql支持了那么多字符集,但是经过上面的分析,可以知道utf8mb4基本可以覆盖99%的场景。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-01-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 突发状况
    • 复盘
    • 一、ASCII码
    • 二、大一统-Unicode
    • 三、UTF-8
    • 四、大功已成
    • 五、扩展
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档