一、什么是字符集

字符集指的是某个范围字符的编码规则

  • 比如utf8字符集对于所有中文汉字采用3个字节来表示(编码),所以我们称utf8为一种字符集。
    • 这里的范围就是指所有的中文汉字
    • 编码规则就是指 都采用3个字节来表示一个汉字
  • 比如ASCII字符集对于所有英文字母采用1个字节来表示(编码),所以我们称ASCII为一种字符集。
    • 这里的范围就是指所有的英文字母
    • 编码规则就是指 都采用1个字节来表示一个字母

二、MySQL客户端和MySQL服务端字符集是如何交互的

1、前置知识

  • MySQL客户端指的不仅仅是MySQL自带的客户端,比如Navicat、MySQL Workbench、SQLyog等可以按照一定协议连接上MySQL服务端的都属于MySQL的一个客户端。
  • 我们知道计算机存储数据其实是存储的二进制数据(在底层其实就是一串0、1组成的字节序列
  • mysql客户端和服务端通信的时候也需要将字符转化为二进制数据后才能通过网络进行发送,这个过程就称为[编码]
    • 那么如何编码呢?一个汉字到底要用几个字节来表示呢?到底要使用多少个字节才能表示一个中文符号呢?这就涉及到我们具体使用的编码[字符集]
  • MySQL服务端收到客户端发来的二进制序列后,将这些二进制序列还原为对应的字符,这个过程就称为[解码]
    • 那么如何解码呢?到底要截取多少个字节才能表示一个汉字呢?到底要截取多少个字节才能表示一个中文符号呢?这就涉及到我们具体使用的编码[字符集]
  • 一般来说编码和解码是成对出现的,有编码就会有解码
  • 一个字符集可以有多种比较规则(比如采用utf8字符集编码后,比较 a = A时可以采用不同的比较规则),每个字符集都有一个默认的比较规则。

2、MySQL客户端和服务端交互

由一条SQL为切入点进行切入(select * from tbl where name = '张三'

假设客户端使用的字符集为gbk,MySQL服务端使用的是utf8字符集来编码并存储数据的。

①、交互流程

  • 首先客户端先连接上MySQL服务器(比如:我们使用Navicat来连接MySQL)
    • 建立连接时MySQL客户端会先获取自己操作系统的字符集(假设是gbk)
    • 然后将字符集、密码、用户名等发送给MySQL服务端
    • MySQL服务端收到连接请求后,验证用户名、密码等。然后为这个客户端连接建立一个session作用范围,然后将客户端所使用的字符集保存到session范围的三个变量上(分别是:[character_set_client、character_set_connection、character_set_results]上),也就是说着三个变量的值都为gbk。具体作用后面说
    • 连接建立完毕
  • 客户端向MySQL服务端发送一条SQL(select * from tbl where name = '张三'
    • MySQL客户端首先要对这条SQL进行编码,按照指定的字符集(比如:utf8、gbk、ASCII等)进行编码,然后发送给MySQL服务端。
  • MySQL服务端收到SQL,然后查看该session中的character_set_connection变量的值(这里假设是gbk),对客户端发来的SQL进行解码。此时就能正确的解析出客户端发送的SQL内容了。
  • 然后MySQL服务端就可以按照SQL内容去执行筛选和查询了。
  • MySQL服务端查询完数据后要将数据返回给客户端,此时MySQL服务端会先查看[character_set_results]变量的值,得到编码的字符集(gbk),然后使用该字符集对返回数据进行编码。然后发送给客户端
  • 客户端收到数据后,按照操作系统的字符集对服务端响应的数据进行解码。交互完成
②、特殊情况

假设客户端是按照gbk字符集进行的编码,MySQL服务端也是按照gbk字符集进行解码的,这两步没有问题。但是MySQL存储数据的时候使用的字符集却是utf8。这可完犊子了,对于过滤条件name = '张三'到底是使用gbk的比较规则还是使用utf8的比较规则去比较呢?

MySQL规定:数据存储的字符集和对应的比较规则优先级更高,此时就需要将原本按照gbk编码、解码的数据重新转换为utf8字符集,然后使用utf8对应的比较规则去比较!

三、MySQL常用字符集介绍

①、字符集列表
字符集名称占用字节数
ASCII1
gbk1 ~ 2
utf81 ~ 3
utf8mb41 ~ 4
  • ascii字符集只收录了128个字符,包括空格,标点符号,数字,大小写字母和一些不可见字符,不能表示中文。

  • gbk字符集收录了汉字(6763个)以及拉丁字母、希腊字母、日文、俄文等字符,同时这种字符集又兼容ASCII字符集。当字符再ASCII字符集表示范围内的话就采用一个字节表示,否则采用两个字节表示。

  • 在MySQL中utf8字符集是经过MySQL设计者阉割过后的字符集(为了尽可能省空间),该字符集最大使用3个字节来表示一个字符,不可以存储表情或某些非常特殊的字符,在数据库字符集、表字符集、列字符集等选型的时候需要注意了。

  • MySQL一般建议使用utf8mb4字符集,该字符集最大使用4个字节来表示一个字符,可以存储表情或某些非常特殊的字符。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐