6.1 基础扫盲
6.1.1 关于字符集
字符集就是指 符号 和 字符编码 的集合
6.1.2 关于校对规则
校对规则是指一种比较字符集中字符的规则。也有些资料将其称为排序规则
如果我们比较多个字符的值,最简单的方式是按照定义好的规则直接比较其编码。校对规则的核心就是比较字符编码的方式。
我们将这类最简单的比较所有可能性的校对规则,称为 二元校对规则
大小写不敏感校对规则:在比较时,就需要首先将a、b视为等同于A、B,而后再比较编码
6.2 支持的字符集和校对规则
使用 show character set 语句,可以知道数据库当前支持哪些字符集
GBK2312:简体中文及常用符号,双字节编码
BIG5:繁体中文
GBK:中、日、韩,双字节编码
GBK2312、BIG5为GBK的子集。子集中的字符转换成超集中保存不会丢失信息(不会乱码),反之则不一定。
UTF8:包括西、中、日、韩、法、俄等各种文字。英文一字节编码,多字节字符(如中文)使用3个字节编码。
UTF8MB4:UTF8的超集,自MySQL5.5版本开始引入,为了处理像emoji这类表情字符。一个字符使用4个字节编码。
GBK2312,BIG < GBK < UTF8 < UTF8MB4。前面是后面的子集
显式字符集的校对规则,例如utf8:show collation like 'utf8%';
Default 列显示了校对规则是否是该字符集的默认规则
校对规则的特点:
1)每种校对规则只属于一种字符集
2)每种字符集都拥有一个默认的校对规则
3)校对名称的规则:开头的字符是校对规则所属的字符集,_ci 大小写不敏感,_cs 大小写敏感,_bin 二元校对规则,二元校对规则也一定是大小写敏感的规则
6.3 指定字符集和校对规则
字符集和校对规则的设定,从大的维度上来说,有两个层次:
1)连接数据库,执行操作时所用的字符集
2)保存数据时所用的字符集
连接时的字符集和保存时的字符集完全有可能不一样
6.3.1 服务端设置默认字符集
MySQL服务启动过程中,字符集的设定就已经生效,系统会确定默认所使用的字符集和校对规则,并且在启动时指定的字符集合校对规则,对应整个MySQL服务的全局有效。也就是说,如果没有在更细的粒度对字符集合校对规则进行设置,那么接下来的所有操作,其字符集的设定都会继承全局粒度所设定的默认字符集和校对规则。
编译MySQL软件时指定的两个参数:
这两个参数决定了本机所运行的MySQL服务,在没有做任何其他字符集相关设定的情况下默认时的字符集和校对规则。
全局粒度的设置:
1)在编译安装MySQL(仅限源码编译安装方式)时指定
编译MySQL数据库时,可以通过 default_charset 和 default_collation 两个编译参数,指定默认的字符集和校对规则。不明确指定,默认会用 latin1字符集和latin_swedish_ci 校对规则
2)启动MySQL服务时通过参数指定
启动MySQL数据库服务时,其中与字符集相关的是下面两项系统参数:
--character_set_server:指定全局粒度的默认字符集
--collation_server:指定全局粒度的默认校对规则
这两个参数有默认值,是继承编译软件时的两个参数。如果管理的MySQL数据库并非源码编译安装,它们的默认值不一定是 latin1 字符集和 latin_swedish_ci 校对规则(某些类型的安装包可能设定其他字符集)
3)参数文件中配置
MySQL服务启动时,可以通过指定一个参数文件的形式(也就是前面创建的my.cnf文件),来简化启动命令行中指定的选项,同样可以将字符集和校对规则的参数设置放在参数文件中。不过指定参数时不需要“--”字符了。
4)MySQL服务运行期间修改
这两项参数,在MySQL服务运行期间作为系统变量存在,而系统变量在MySQL服务运行期间,多数都是可以被实时修改的,控制字符集和校对规则的系统变量就属于可以被修改的一类。
我们可以通过show variables命令查看当前的系统变量及其变量值。比如说。执行show variables语句查看字符集和校对规则这两项系统变量的值:
若要将全局粒度的字符集改为gbk,那么执行下列命令即可:
collation_server参数的值,也发生了变化。这是因为校对规则是基于字符集的,尽管没有显示修改,但它的值也自动被修改为所设定的 gbk 字符集的默认校对规则。
在MySQL服务运行期间,修改系统变量的值也是有作用域的。MySQL中的系统变量的作用域分为 全局(global) 和 当前会话(session) 两类
对于全局的修改,作用于修改成功后新创建的会话,但对当前执行修改的会话无效,如果是会话级的修改(执行SET命令并且未指定 global 选项就是会话级修改),则只作用于当前会话,本次会话结束后,所做的修改也会自动结束。
此外,需要注意MySQL中即使是全局的参数修改,其作用域最多也只在当前MySQL服务的生命周期内,MySQL服务一旦重启,那么之前的设置也全部无效(不管全局还是会话)。因此要是希望所做的设置永久生效,那么除了在全局粒度修改外,还必须手动修改初始化参数文件,或者是在启动MySQL服务时,在命令行中显示指定相关选项值。
6.3.2 连接时指定
客户端连接到 MySQL 数据库服务后所使用的字符集,与MySQL服务中设定的若干系统变量有关,默认会继承和使用 MySQL服务中设置的字符集。
字符集并不仅仅只有当存取字符数据时才需要,在客户端与MySQL服务器端通信时,字符集同样起着重要作用。很多情况下,显示的字符有乱码,也有可能是因为客户端当前的字符集设置与MySQL服务器端保存字符时所用的字符集不相符所致的。
例如:首先创建一条会话插入一条记录:
而后在另一个会话中读取这条记录,显示的结果却有所不同:
对客户端使用的字符集进行设置
修改了客户端会话中的某个变量值,字符被正确显示出来
与连接相关的字符集变量不再是 character_set_server 。客户端信息大致的处理过程如下:
1)客户端发出的SQL语句,字符集变量由系统变量 character_set_client 来指定
2)MySQL 服务端收到语句后,会用到 character_set_connection 和 collation_connection 两个系统变量中的设置,并且会将客户端发送的语句字符集由 character_set_client 转换到 character_set_connection(除非用户执行语句时,已对字符列明确指定了字符集)。对于语句中指定的字符串的比较或排序,还需要应用collation_connection中指定的校对规则处理,而对于语句中指定的列的比较则无关 collation_connection 的设置了,因为对象的表列拥有自己的校对规则,它们拥有更高的优先级。
3)MySQL服务端执行完语句后,会按照 character_set_results 系统变量设定的字符集返回结果集(或错误信息)到客户端
这些系统变量值的信息查看,使用 show variables:
这几个系统变量的值,默认继承自服务端启动时默认的字符集设置,也就是编译时指定的utf8。
当前的输出结果为全局的设置。当前,每个连接到 MySQL服务的会话,均可以单独设置连接时的字符集,而且针对这几个系统变量,一般也都只设置会话级的变量值
会话级的系统变量值:
与全局时的有所不同。在创建会话连接后,修改与字符集相关的设定:
1)SET NAMES
SET NAMES 命令的功能是指定客户端当前会话使用的字符集
功能上理解,SET NAMES相当于同时执行了下列设置:
2)SET CHARACTER SET
语法:
相当于设置:
@@character_set_database 表示全局变量
例如,设置当前会话的字符集为latin1
usc2、utf16、utf16le 和 utf32 不能被作为客户端字符集使用,也就是说使用 SET NAMES 或 SET CHARACTER SET命令设置这类字符集无效
3)固化连接时的字符集设置
SET NAMES命令 和 SET CHARACTER SET 命令都是基于会话设定的,仅作用于当前会话,退出登录后所做设置就失效了。
一方面,可在启动MySQL服务时,通过设置相关系统变量,达到永久生效的目的。
另一方面,在客户端进行设置,使得与MySQL相关的客户端命令在连接时,能够自动使用我们设定好的字符集,避免每次会话操作前再单独设定。