赞
踩
在学习和开发过程中偶尔会遇到乱码问题,解决问题首先想到的就是修改字符集,但又因为对字符集这个东西一知半解感觉无从下手,本文就聊聊字符集,旨在分享和学习,希望对大家有所帮助!
注: 文章引出字符集概念主要是为了讲解数据库utf8 、utf8mb3 和 utf8mb4 的区别,以及utf8mb4_unicode_ci 和 utf8mb4_general_ci的区别
首先,了解以下几个老生常谈的概念:
位: 位(bit)是计算机最小的存储单位,由于计算机世界里只有逻辑0和逻辑1的存在,所以信息只能以一串二进制字码的形式存储到计算机中,如数字8保存到计算机里就是0000 1000,其中每个0和1即为一个位。
字节: 一个字节(Byte)由8个位组成,可以用它来记录表示字母和一些符号,例如大写字母L就用0100 1100来表示(可以对照下面的ASCII码表)。
字符: 即文字符号,包含文字,标点符号,数字,图形符号等(最直观的例子就是各国语言文字、数字、符号等)。
字符集: 是多个字符的有序
集合,常见的有ASCII(美国信息交换标准代码,如下图)、Unicode、GB2312、ISO-8859-1等字符集。
字符编码: 计算机本身只认识数字0和1,所以字符对它来说是无法识别的,更不用说字符集了,因此要将这套字符编码成为计算机可识别的二进制编码,这个将字符集转换为字节码流的过程即字符编码。
解码: 字符编码的逆过程,将字节码流转换成我们熟悉的字符集。
那么问题来了,为什么要有多种字符集?
先举个例子:
我制订了一套标准,给所有汉字从1开始标号,大概就是1-100,000(中国大约有10万个汉字),每个数字分别对应一个汉字,这样每个汉字有了它唯一的数字编号,然后我把这套标准起名BB并录入了计算机系统,且使用起来流畅无误,然后由于实用性强得到了全国普及,这时候突然有个外国佬发现他的程序出现了乱码,一查发现是因为这套程序是用的BB这个标准,他是按照自己国家的另一套编码解出来的,编码解码标准不对应产生错误字符从而出现了乱码,这时候他的计算机就不得不兼容我这套标准,而我的标准由于流行度高被国际认可,于是国际上就多了一套字符集。
由此可知,乱码就是编码和解码时采用的编码方式不一致导致的!比如 ISO-8859-1 字符集里没有中文字符,用这套标准编码再解码同样会出现乱码。
ASCII: (American Standard Code for Information Interchange),美国信息交换标准代码,它是最早产生的编码规范,也是最通用的信息交换标准,共有0000 0000~0111 1111的128个字符,能表示数字、大小写英文字母和一些简单的符号,后来IBM公司扩展了最高位,但就算这样最多也只能标识256个字符。
Unicode: 是国际化标准组织(ISO)制定的一种世界通用的编码规范,包含了全世界所有的字符,规定必须用两个字节来标识一个字符,也就是16位来统一表示所有字符,总共可以包含65535个不同字符,最多可以保存4个字节容量的字符。
由上图中可知,ASCII是一种单字节的编码标注(只需用8个位就能表示一个字符),却只有128个字符(加上最高位也才256个),这对其他国家来说就不够友好,说白了就是三个字:不够用
,所以各个国家就在ASCII码的基础上进行扩展(这也是为什么编程尽量使用英文,因为英文乱码概率低),我国也有了GB2312字符集和GB18030字符集。
后来国际化标准组织(ISO)觉得一人搞一套那也太乱了,就制定了一个通用编码规范供大家一起用,这就是Unicode,即我们常说的万国码(也叫统一码)!
总结可得:有多种字符集是因为每个字符集包含的字符数量不同,然而各国的字符内容不一,需求不一,这就不得不新增一种标准,于是就出现了 ASCII 字符集、GB2312 字符集、ISO-8859-1 字符集、 GB18030 字符集、Unicode 字符集…
大家都知道,在新建数据库的时候,我们需要填写数据库名、字符集和排序规则,如下图:
如果只填写数据库名也可以,不过会生成默认的字符集和排序规则,如下图:
那么这些字符集和排序规则到底有什么区别呢?我们在使用时如何选择?今天就和大家一起来探讨下这个问题!
点此可以查看mysql官网8.0版本关于字符集的详细内容说明
1. utf8
由于Unicode字符集规定必须用两个字节,也就是16位-32位,那些只需一个字节的字符在互联网上进行传输的时候就会比较浪费网络带宽资源,于是出现了一些中间格式的字符集,被称为统一的转换格式(Unicode Transformation format),即UTF编码,UTF-8是针对Unicode的一种可变长度字符编码。
一个英文字符在UTF-8编码中占一个字节, 一个汉字占三个字节。
utf8 是 MySQL中的一种字符集,utf8是utf8mb3的别名,除此之外并无不同(如下图,MySQL官网已经给出说明)
2. utf8mb3
3. utf8mb4
mb4即 most bytes 4,即最多使用4个字节来表示完整的UTF-8,具有以下特征:
它是utf8的超集并完全兼容它,是MySQL 在 5.5.3 版本之后增加的一个新的字符集,能够用四个字节存储更多的字符,几乎包含了世界上所有能看到见的语言字符。
4. 差异比较
差异点 | utf8mb3 | utf8mb4 |
---|---|---|
最大使用字节数 | 3 | 4 |
支持字符类型 | BMP | BMP+其他补充字符 |
字符类型 | 常见的 Unicode 字符 | 常见的 Unicode 字符 + 部分罕用汉字 + emoji表情 + 新增的 Unicode 字符等 |
Unicode范围 | U0000 - U+FFFF(即BMP) | U0000 - U+10FFFF |
占用存储空间 | 略小(如CHAR(10) 需要10 * 3 = 30 个字节的空间;VARCHAR 类型需要额外使用1个字节来记录字符串的长度) | 稍大(如CHAR(10) 需要 10 * 4 = 40 个字节的空间;VARCHAR 类型需要额外使用2个字节来记录字符串的长度) |
兼容性 | 切换至utf8mb4 一般不会有问题,但要注意存储空间够不够、排序规则是否变化 | 切换至utf8mb3可能会有问题,字符丢失、报错或乱码 |
安全性 | 稍低,更容易被恶意字符串攻击 | 较高,保留恶意字符串,然后报错或乱码提示 |
一句话就是,根据具体的业务需求和实际情况,选择最合适的字符集。
排序规则(collation),字符串在比较和排序时所遵循的规则。不同的字符集有不同的排序规则,同一个字符集也可以有多种排序规则。在 MySQL 8.0.1 及更高版本中将 utf8mb4_0900_ai_ci(属于 utf8mb4_unicode_ci 中的一种) 作为默认排序规则,在这之前 utf8mb4_general_ci 是默认排序规则。
MySQL常用排序规则有:utf8mb4_general_ci、utf8mb4_unicode_ci、utf8mb4_bin、utf8mb4_0900_ai_ci
_bin : 按二进制方式比较字符串,区分大小写和重音符号。
_ai_ci:按照特定语言或地区方式比较字符串,不区分大小写和重音符号。
_unicode_ci: 按 Unicode 标准方式比较字符串,不区分大小写和重音符号。
_general_ci:按一般方式比较字符串,不区分大小写和重音符号。
utf8mb4_unicode_ci: 能够在各种语言之间精确排序,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。
utf8mb4_general_ci: 不支持扩展,它仅能够在字符之间进行逐个比较。utf8_general_ci 比较速度很快,但比 utf8mb4_unicode_ci 的准确性稍差一些。
utf8mb4_unicode_ci 是精确排序,utf8mb4_general_ci 没有实现 Unicode 排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。
因此,准确性是utf8mb4_unicode_ci > utf8mb4_general_ci
utf8mb4_general_ci 在比较和排序的时候更快。
utf8mb4_unicode_ci 在特殊情况下,Unicode 排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。
因此,性能方面是utf8mb4_general_ci > utf8mb4_unicode_ci
如果在创建数据库时对特殊字符的顺序并不需要那么精确,排序规则可使用utf8mb4_general_ci 。推荐用 utf8mb4_unicode_ci,但是用 utf8mb4_general_ci 也没问题
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。