「引言」
对于使用MySQL来说,有一个让人苦恼的事情就是处理字符集的问题,众多的字符概念和设置,常常让用户感到束手无策而不知如何使用。对事务所来说客户的需求就是我们命令,了解到大家的这种困惑后。经过一番探索,X侦探所的探员T将给大家捋顺字符集的来龙去脉以及MySQL中的字符集秘密,下面就将开启我们的字符探索之旅。
我们知道这个世界上有各种各样的文字,这些文字是能够通过书写进行记录的,比如古印度的贝叶,欧洲的羊皮卷,中国四大发明之一的纸都是文字记录的载体。落于纸面的文字就要使用符号,我们所熟悉的中文使用的是表意的象形字符,英文使用的是表音的字母,通过字符或者字母的组合记录信息。英文字母有26个,而有记载的中文汉字却有8万个之多。
在计算机世界,是使用数字进行信息记录的,不论是中文的字符还是英文的字母在都将以数字的方式进行表示。比如英文小写的a,在计算机内用数值97来代表,这些代表字母或者汉字以及各种符号(如 -*/这些符号)的数字集合就被称为字符集,也就是字符数字化后的数字集合。在早期的计算机世界中,对于不同文化的文字,没有一个统一的规划,每个国家都有自己的字符集。以Centos操作系统为例,使用locale -av命令可以查看系统支持哪些语言文字的字符集。
下图列出部分locale输出的内容,如utf8编码中国香港字符集:
如ISO-8859-1编码的比利时字符集:
有兴趣的同学可以深入的研究字符集。
「第二部分 介绍」
首先,我们先看看MySQL有哪些关于字符集的变量,如下图所展示:
下面我们就这些变量一一进行说明,与MySQL的文档不同,此处我们尽可能的用实际的例子来说明这些变量的用处。
character_set_client
这个变量是让很多人困惑的,它代表的是当前客户端的字符集,以Centos操作系统为例,使用mysql客户端
当centos的环境变量LANG为en_US.UTF-8时,character_set_client就会是utf8,当环境变量LANG为C时,character_set_client就会是latin1。如下图所示:
这个变量是供用户客户端进行展示所使用的字符集,比如在这里是MySQL的命令行客户端,对外展示的是latin1字符集,在其他场合这个客户端也可以是图形化的。客户端展示字符的字符集,就是变量character_set_client所指的字符集。
character_set_connection
这个变量是用于MySQL在传输过程中所使用的字符集,当服务器和客户端进行通讯时,接受到客户端的请求后,需要将客户端的字符集转换为服务器所使用的字符集,并使用该字符集进行操作。在完成请求的处理后,再将处理结果转换为客户端的字符集返回给客户端。
character_set_database
这个变量在完成use dbname后,和当前数据库默认字符集是一致的。在alter table convert to character set default时,将表的默认字符集转换为该变量所指定的字符集,而不是该表所在数据库的默认字符集。
character_set_filesystem
这个变量是用于说明文件系统所使用的字符集,在执行SQL向磁盘写入文件,比如into outfile 或者dumpfile,将SQL中的字符集转换为操作系统的字符集。
比如这个例子,MySQL如果要打开/tmp/x这个文件,必须要通过操作系统的字符集来打开文件,需要将SQL语句的字符集转换为操作系统的字符集,这就是这个变量的作用。
character_set_results
这个变量是生成结果集时,结果集所使用的字符集。比如查询语句select所生成结果集,其中每一行都是都是character_set_results所指定的字符集。
character_set_server
该变量指明服务器级别的字符集,其作用在于,比如当create database不指定字符集时,使用该变量的字符集作为database的默认字符集。
character_set_system
这个变量是只读的全局变量,并且不能在启动参数或者配置文件中进行设置,该变量的默认值是utf8。这个变量是作用于标识符的,比如列名、表名,这些标示符的字符串的存储与比较都是用这个变量所指的字符集,该字符集仅用于内部。
character_sets_dir
MySQL的字符集是通过一系列XML定义的。这个变量就是指定MySQL所使的字符集定义的XML文件,这部分深入下去的话涉及到字符集的具体实现细节。此处用户需要了解的是,这个是MySQL自己内部使用,不提供对外的设置的变量。
至此,MySQL中关于字符集的主要变量都介绍完了,在这里再次停顿,来做一次总结,概括一下字符集使用情况。
(1)执行过程中的字符集 如下就是客户端向服务器请求时的字符集转换过程,从phpMyAdmin客户端向服务器插入,从服务器进行查询,这两个字符的过程。
(2)set names 如果一次操作中涉及了多次字符集的转换,所产生一个负面问题就是效率问题,数据需要在不同的字符集之间进行转换,这可能成为性能上的瓶颈,所以在实际使用中,尽可能的保持字符集的一致。这可以通过set names来进行统一的设置。
如上图,character_set_client、character_set_connection和character_set_results这三个变量通过set names保持了一致,就减少了在请求处理上数据传输字符集的转换。但这并不是最极致的,应该尽可能保持存储的数据以及set names的字符是一致的,这样就会减少字符集转换的带来的性能下降。
「第三部分 结束语」
T探员语:即使是事务所的探员们,也每每都被MySQL的各种字符集搞得头晕脑胀,这次总算梳理出了一个脉络。为了帮助大家理解,X事务所的探员们尽可能的通过举例的方式向大家展示抽象的内容,如果大家有什么建议可以反馈给我们,我的探员同事们可是很希望能够为大家提供帮助和支持的哦:)
腾讯数据库技术团队对内支持QQ空间、微信红包、腾讯广告、腾讯音乐、腾讯新闻等公司自研业务,对外在腾讯云上依托于CBS CFS的底座,支持TencentDB相关产品,如CynosDB、CDB、CTSDB、MongoDB、CES等。腾讯数据库技术团队专注于持续优化数据库内核和架构能力,提升数据库性能和稳定性,为腾讯自研业务和腾讯云客户提供“省心、放心”的数据库服务。此公众号旨在和广大数据库技术爱好者一起推广和分享数据库领域专业知识,希望对大家有所帮助。