
3.3 MySQL 8新特性:字符集与排序规则
MySQL支持字符集,能够实现使用多种字符集存储数据。MyISAM、MEMORY和InnoDB存储引擎支持使用字符集。字符集问题不仅影响数据存储,还影响客户端程序与MySQL服务器之间的通信。
3.3.1 一般字符集和排序规则
字符集是符号和编码的集合,排序是规则的集合。假设有一个包含A、B、a、b的字母表,给每个字母设定一个值:
A=0 B=1
此时要比较A与B的大小,可以直接比较设定的值,所以A小于B。B以及它们的编码值组成的集合就成为字符集,判断大小时使用比较编码的规则就成为排序。
实际应用中,字符集更复杂,可能包含整张字母表,或数张字母表以及包含几千个字符的东方文字系统,例如汉字,排序规则也会更多。
在实际操作中,往往需要实现以下功能:
(1)使用多种字符集存储字符串。
(2)使用多种规则比较字符串。
(3)在同一个服务器、数据库甚至是数据表中混合使用多种不同的字符集和字符串。
(4)在任何层面上设置字符集和排序规则可用。
在MySQL中,要想高效地使用这些特征,必须确定支持哪些字符集和排序、如何修改默认设置以及这些特征如何影响字符串的操作和函数。
3.3.2 MySQL中的字符集和排序规则
MySQL服务器支持多种字符集。查看可用的字符集,可使用INFORMATION_SCHEMA库中的CHARACTER_SETS表或SHOW CHARACTER SET语句,如图3-21所示。

图3-21 查看字符集
字符集至少包含一种排序,在图3-21中,“Default collation”显示的是当前默认排序,要查看所有排序可使用INFORMATION_SCHEMA库中的COLLATIONS表或SHOW COLLATION语句。默认情况下,SHOW COLLATION语句显示所有可用的排序,可使用LIKE或WHERE语句指定显示某个或某些字符集的排序,如图3-22所示。

图3-22 查看字符集的排序
排序有如下特点:
(1)两个不同的字符集不能有相同的排序。
(2)每个字符集都有默认的排序,例如utf8mb4和latin1字符集的默认排序分别为utf8mb4_0900_ai_ci和latin1_swedish_ci。
(3)排序名称以字符集名称开始,通常后边跟一个或多个后缀表示其他的特性。
1. 字符集编码表
字符集编码表是字符集中的字符集和。字符串表达式的编码表属性包含两个值:
(1)ASCII:表达式只能包含Unicode码从U+0000到U+007F。
(2)UNICODE:表达式包含Unicode码从U+0000到U+10FFFF。
ASCII是UNICODE的子集。ASCII字符编码可以被无损地转化为任何UNICODE编码或者其他ASCII的父集。
字符集编码表有如下特点:
(1)字符串的编码表取决于字符串内容,有可能与字符集的编码表不同。例如:
SET NAMES utf8; SELECT 'abc'; SELECT _utf8'def'; SELECT N'MySQL';
虽然字符集是utf8,但是字符内容并不包含超出ASCII编码表范围的内容,所以它们的编码表是ASCII而不是UNICODE。
(2)含有一个字符串参数的函数继承参数的编码表。
(3)返回字符串但没有字符串参数,并且使用character_set_connection变量设置的函数,其编码表为character_set_connection设置的编码表。
(4)含有两个及以上字符串参数的函数使用“最宽的”参数编码表作为编码表。如果在两个参数中,一个为ASCII字符集,另一个为UNICODE字符集,那么函数的编码表为UNICODE。
2. 元数据的UTF-8编码
元数据是“关于数据的数据”。与数据库内容相对的其他任何描述数据库的内容都是元数据。因此,列名、数据库名、版本名、用户名以及大部分show语句展示的结果都是元数据。INFORMATION_SCHEMA库中的表内容也是元数据,因为这些表由关于数据库对象的信息定义。
元数据满足以下特点:
(1)所有的元数据必须为同一个字符集,否则在INFORMATION_SCHEMA中SHOW语句或SELECY语句无法正常运行。
(2)元数据必须包含所有语言所用到的所有字符,否则使用者无法使用自己的语言命名列和表。
为满足以上需求,MySQL使用UNICODE字符集存储数据,命名为UTF-8。
服务器设置系统变量character_set_system的值为元数据的编码名称,可使用show语句查看,如图3-23所示。

图3-23 查看编码
使用SELECT语句时,返回的字符集取决于character_set_results系统变量,该变量设置的默认值为utf8mb4。如果想要服务器以不同的字符集传递元数据结果,使用SET NAMES语句强制服务器完成字符集转换,也可以通过客户端接收到结果后再转换,但不是所有的客户端都能满足要求。
如果character_set_results设置的值为空,那么服务器不会进行转换,并且会以初始化的字符集返回元数据。初始化的字符集由character_set_system变量设置。
3.3.3 指定字符集和排序规则
在MySQL中,对于字符集和排序有4个层面的默认设置:服务器、数据库、表和列。在语句中可使用CHARACTER SET指定字符集。字符集设置问题不仅影响数据存储,还影响客户端程序与服务器之间的通信。
1. 排序命名约定
MySQL排序的名称遵循以下约定:
(1)排序名称以字符集开头,以一个或多个后缀标明其他特性。例如,utf8mb4_general_ci是utf8mb4的排序。
(2)指定语言的排序包括本地编码或语言名称。例如,在utf8mb4_tr_0900_ai_ci中,tr表明该排序使用土耳其(Turkish)的规则排序。
(3)排序后缀指明这个排序是否区分大小写或重音。常见后缀含义如表3-8所示。
表3-8 常见后缀含义

(4)对Unicode字符集,排序名称可能包含版本号数字来指明对应的Unicode排序算法(UCA)的版本号。如果不包含版本号,就默认使用版本4.0.0。例如:
- utf8mb4_0900_ai_ci基于UCA 9.0.0;
- utf8mb4_unicode_520_ci基于UCA 5.2.0;
- utf8mb4_unicode_ci基于UCA 4.0.0。
2. 服务器字符集和排序
MySQL服务器的字符集和排序可在服务器启动时通过命令或在配置文件中设置,在运行时可以修改。服务器字符集和排序取决于你启动mysqld时使用的配置项,可以使用--character-set-server设置,在这个命令之后可以加上--collation-server设置排序。如果不指定字符集,默认为utf8mb4。如果只指定字符集,不指定排序,就使用字符集对应的默认排序。若要查看字符集的默认排序,则可参考3.3.2小节。
3. 数据库字符集和排序
数据库包含自己的字符集和排序。CREATE DATABASE和ALTER DATABASE语句都可使用选项指定数据库的字符集和排序。
CREATE DATABASE db_name [[DEFAULT] CHARACTER SET charset_name] [[DEFAULT] COLLATE collation_name] ALTER DATABASE db_name [[DEFAULT] CHARACTER SET charset_name] [[DEFAULT] COLLATE collation_name]
在MySQL中,可使用如下语句查看数据库对应的字符集和排序,如图3-24所示:
SELECT @@character_set_database, @@collation_database;

图3-24 使用命令查看数据库字符集和排序
也可以通过INFORMATION_SCHEMA库中的SCHEMATA表查看,如图3-25所示。

图3-25 查看数据库字符集和排序
MySQL按照如下规则确定数据库的字符集和排序:
(1)创建时,同时指定字符集和排序,使用指定的字符集和排序。
(2)只指定字符集,不指定排序,使用字符集对应的默认排序。
(3)只指定排序,使用排序对应的字符集。
(4)字符集与排序都不指定,选择服务器的字符集和排序。
4. 表字符集和排序
每张表都有字符集和排序。CREATE TABLE和ALTER TABLE语句由可选的语句指定表的字符集和排序。
CREATE TABLE tbl_name (column_list) [[DEFAULT] CHARACTER SET charset_name] [COLLATE collation_name]] ALTER TABLE tbl_name [[DEFAULT] CHARACTER SET charset_name] [COLLATE collation_name]
在MySQL中,可使用如下语句查看表对应的字符集和排序:
SHOW table status [from database_name] like 'table_name';
MySQL按照如下规则确定表的字符集和排序:
(1)如果同时指定字符集和排序,就使用指定的字符集和排序。
(2)如果只指定字符集,不指定排序,就使用字符集对应的默认排序。
(3)如果只指定排序,就使用排序对应的字符集。
(4)如果两者都不指定,就使用数据库的字符集和排序。
5. 列字符集和排序
每个字符列(CHAR、VARCHAR或TEXT)都有字符集和排序。CREATE TABLE和ALTER TABLE都由可选的列定义语句设置列的字符集和排序。
col_name {CHAR | VARCHAR | TEXT} (col_length) [CHARACTER SET charset_name] [COLLATE collation_name]
这些语句也可用于ENUM和SET列。
col_name {ENUM | SET} (val_list) [CHARACTER SET charset_name] [COLLATE collation_name]
在MySQL中,可使用如下语句查看表中所有列对应的字符集和排序:
show full columns from table_name;
MySQL按照如下规则确定列的字符集和排序:
(1)如果同时指定字符集和排序,就使用指定的字符集和排序。
(2)如果只指定字符集,不指定排序,就使用字符集对应的默认排序。
(3)如果只指定排序,就使用排序对应的字符集。
(4)如果两者都不指定,就使用表的字符集和排序。
【示例3-8】字符集和排序赋值示例。
创建列时,分别以如下情况创建:同时指定字符集和排序、只指定字符集、均不指定,创建完成后分别查看对应列的字符集和排序,如图3-26所示。
CREATE TABLE t1 ( c1 CHAR(10) CHARACTER SET latin1 COLLATE latin1_german1_ci, c2 CHAR(10) CHARACTER SET latin1, c3 CHAR(10) ) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

图3-26 查看列字符集和排序
从图3-26中可以看到,确定列字符集和排序时与上述规则一致。
6. 字符串的字符集和排序
每个字符串都有字符集和排序。
通过字符集导入程序和排序语句可以指定字符串的字符集和排序:
[_charset_name]'string' [COLLATE collation_name]
例如:
SELECT 'abc'; SELECT _binary'abc'; SELECT _utf8'abc' COLLATE utf8_danish_ci;
以上语法中,_charset_name表达式称为导入程序。它告诉解析器,接下来的字符串使用该字符集。
MySQL使用如下规则确定字符串的字符集和排序:
(1)如果同时指定字符集和排序,就使用指定的字符集和排序。
(2)如果只指定字符集,就使用字符集对应的默认排序。
(3)如果只指定排序,就使用系统变量指定的character_set_connection字符集,字符集与排序必须相匹配。
(4)如果两者都不指定,就使用character_set_connection和collation_connection系统变量指定的字符集和排序。
3.3.4 连接字符集和排序规则
“连接”即连接服务器后所做的事情。客户端通过连接向服务器发送语句,服务器通过连接向客户端返回结果集或错误信息。前面的内容中提到,一些系统变量与连接有关。比如,character_set_server和collation_server系统变量的值即为服务器的字符集和排序,character_set_database和collation_database系统变量的值是默认数据库的字符集和排序。
实际上,还有一些系统变量在决定连接的字符集和排序中起着至关重要的作用。MySQL根据以下规则确定连接的字符集与排序:
(1)服务器使用character_set_client系统变量的值作为语句的字符集。
(2)服务器将接收到的语句的字符集由character_set_client的值转换成character_set_ connection的值,除了那些使用引导程序的字符串。字符串之间的比较需要用到collation_connection变量,除了列值之间的字符串比较,因为列都有自己的排序,并且列排序优先。
(3)character_set_results系统变量指定了服务器返回结果的字符集,不仅包括列数据还包括列的元数据。
3.3.5 配置应用程序字符集和排序
如果应用不使用默认的字符集和排序,就需要额外配置,有以下几种方式:
(1)指定每个数据库的字符设置。
使用如下语句创建数据库:
CREATE DATABASE mydb CHARACTER SET latin1 COLLATE latin1_swedish_ci;
在这个数据库下创建的表将会使用latin1和latin1_swedish_ci排序。使用这种方式创建的数据库,应用在每次连接时需要使用SET NAMES或其他等效的方式设置字符集。
(2)在服务器启动时指定字符设置。
使用character-set-server和collation-server配置项指定字符集和排序。例如,在配置文件中使用如图3-27所示的设置。

图3-27 配置文件设置字符集和排序
这些设置适用于服务器、所有程序、所有数据库以及所有表。
在应用连接服务器之后,仍然需要使用SET NAMES或等效的方式设置字符集。
(3)使用源码构建MySQL,可在配置期间指定字符设置。
使用源码构建MySQL时,可在cmake选项中使用DEFAULT_CHARSET和DEFAULT_COLLATION:
cmake . -DDEFAULT_CHARSET=latin1 \ -DDEFAULT_COLLATION=latin1_swedish_ci
这样设置后,服务器使用latin1和latin1_swedish_ci作为默认的字符集和排序。使用这种方式设置字符集,连接时不需要再进行其他设置。
如果不同的应用需要不同的字符设置,可根据具体需求选择设置方式。如果每个应用的字符集都不相同,那么为每个数据库单独指定字符集更灵活。如果大多数应用使用的是相同的字符集,在服务器启动或配置时设置更方便。
3.3.6 错误消息字符集
MySQL服务器使用UTF-8构造错误消息,然后以character_set_results系统变量指定的字符集返回给客户端。客户端可以设置character_set_results来决定使用哪个字符集接收错误消息。
服务器通过如下内容构造错误消息:
(1)消息模板使用UTF-8。
(2)模板中的参数被具体错误情况中的值替代。
(3)为了向客户端返回消息,服务器将消息从UTF-8转化为character_set_results系统变量设置的值。如果该值为空或为utf8,就不会转化。
3.3.7 列字符集转换
如果要将字符串列转化成特定的字符集,需使用ALTER TABLE语句。为了成功转换,必须满足下列条件之一:
(1)如果列使用二进制数据类型,即BINARY、VARBINARY和BLOB类型,所有包含的值必须使用统一的字符集编码。若使用多种编码存储信息,则不能正常转换。
(2)如果列使用非二进制类型,即CHAR、VARCHAR和TEXT类型,可以直接转换为列的字符集编码。如果转换成别的字符集,需要首先把列转为二进制类型,然后转为目标字符集。
3.3.8 排序问题
1. 在SQL语句中使用COLLATE
使用COLLATE子句可以覆盖默认的排序。下面的语句展示了部分使用场景。
#用于ORDER BY语句 SELECT k FROM t1 ORDER BY k COLLATE latin1_german2_ci; #用于AS语句 SELECT k COLLATE latin1_german2_ci AS k1 FROM t1 ORDER BY k1; #用于GROUP BY语句 SELECT k FROM t1 GROUP BY k COLLATE latin1_german2_ci; #用于聚合函数 SELECT MAX(k COLLATE latin1_german2_ci) FROM t1; #用于DISTINCT语句 SELECT DISTINCT k COLLATE latin1_german2_ci FROM t1; #用于WHERE语句 SELECT * FROM t1 WHERE _latin1 'Müller' COLLATE latin1_german2_ci = k; #用于HAVING语句 SELECT k FROM t1 GROUP BY k HAVING k = _latin1 'Müller' COLLATE latin1_german2_ci;
2. COLLATE子句优先级别
COLLATE子句拥有高优先级,比“||”要高。
3. 字符集和排序兼容性
一个字符集拥有一个或多个排序,但一个排序只对应一个字符集。
4. 表达式的排序可压缩性
对于大多数语句,MySQL能够确定排序,但多操作数或多参数级联操作中可能存在歧义。为了解决这些问题,MySQL规定了表达式可压缩性的值,如下所示:
(1)明确的COLLATE子句可压缩性为0。
(2)在级联操作中,使用不同排序的两个字符串可压缩性为1。
(3)列或已存储的程序参数或本地变量可压缩性为2。
(4)系统常量可压缩性为3。
(5)文字可压缩性为4。
(6)数字或临时的值可压缩性为5。
(7)NULL或为NULL的表达式可压缩性为6。
MySQL根据如下规则运用可压缩性的值,解决歧义问题:
(1)使用可压缩性值最小的排序。
(2)如果两边可压缩性相同,且都是Unicode或都不是Unicode,就报错;如果一方是Unicode,就使用Unicode一方的排序,并自动转换非Unicode一方。
(3)如果多操作数的操作中混合了_bin排序和_ci或_cs排序,就使用_bin排序。
5. 二进制排序与后缀为_bin的排序对比
二进制字符串拥有的字符集和排序叫binary。非二进制字符串拥有除二进制之外的其他字符集和排序,其中有后缀为_bin的二进制排序。二进制排序binary与后缀为_bin的排序有如下不同。
(1)对比和分类的单元
二进制字符串是字节序列,非二进制字符串是字符序列。非二进制字符串的排序定义了字符值,_bin后缀的排序基于此数值。
(2)字符集转换
非二进制字符串在很多情况下会被自动转化成另一个字符集,尽管它的排序是以_bin后缀结尾的排序;而对于二进制字符串列,则不会转换。
(3)大小写字母转换
非二进制字符集的排序提供了字符的字母大小写信息,所以非二进制字符串可以转换字母的大小写状态,即使使用的是忽略大小写的_bin排序。
二进制字符串中没有字母大小写的概念。如果要转换,就必须先转换成非二进制字符串。
(4)比较中的空格处理
大多数MySQL排序都有pad属性PAD SPACE,而基于UCA9.0.0及以上版本的Unicode排序拥有的pad属性为NO PAD,pad属性决定了该排序如何处理尾部空格。
在非二进制字符串中,NO PAD排序对待尾部空格如同正常字符串,而在PAD SPACE排序中,尾部空格无意义。
在二进制字符串中,所有的字符都有意义,包括尾部空格。
(5)插入和检索的尾部空格处理
CHAR(N)列存储非二进制字符串。插入时,比N长度短的字符会被空格填充。检索时,尾部空格被移除。
BINARY(N)列存储二进制字符串。插入时,长度小于N的值使用0x00字节填充。检索时,不移除该字节,返回的长度始终是声明的长度N。
3.3.9 Unicode支持
Unicode标准包括基础语言平台(Basic Multilingual Plane,BMP)的字符和平台之外的辅助字符。
BMP字符有如下特点:
(1)代码点值在0~65535之间。
(2)可使用可变长度的编码,8位、16位或24位。
(3)可使用固定16位长度的编码。
(4)对大多数语言已足够。
辅助字符在BMP之外,有如下特点:
(1)代码点值在U+10000和U+10FFFF之间。
(2)Unicode支持辅助字符,但字符集的范围在BMP之外,因此比BMP占用更多的空间。
UTF-8是一种演变的Unicode,使用可变长度的字节序列编码,拥有如下特点:
(1)基础拉丁字母、数字和标点符号使用一个字节。
(2)大多数欧洲和中东的脚本字母适合两个字节的序列。
(3)韩语、汉语和日语使用3个字节或4个字节序列。
MySQL支持以下Unicode字符集:
(1)utf8mb4:每个字符使用1~4字节的UTF-8编码。
(2)utf8mb3:每个字符使用1~3字节的UTF-8编码。
(3)utf8:utf8mb3的别名。
(4)ucs2:每个字符使用2字节的UCS-2编码。
(5)utf16:每个字节使用2或4字节的UTF-16编码,支持辅助字符扩展。
(6)utf16le:UTF-16LE编码,类似utf16,但是使用小字节序。
(7)utf32:每个字符使用4字节的UTF-32编码。
MySQL所支持的Unicode字符集的一般特性如表3-9所示。
表3-9 Unicode字符集的一般特性

3.3.10 支持的字符集和排序规则
1. Unicode字符集
3.3.9小节中已列出了MySQL支持的Unicode字符集,大多数Unicode字符集拥有一个通用排序、一个二进制排序和其他几个含有语言标识的排序。通用排序通常以“_general”指定,二进制排序通常以“_bin”指定,其他排序通常以语言指定。例如,对于utf8字符集,utf8_general_ci为通用排序,utf8_bin为二进制排序,utf8_danish_ci是其中一个以语言标识指定的排序。常见的Unicode排序语言标识如表3-10所示。
表3-10 Unicode排序语言标识

2. 亚洲地区字符集
MySQL支持的亚洲语言有中文、日语、韩语和泰语,这些语言相对较复杂。
(1)cp932字符集
cp932字符集支持扩展字符,对日语的支持更友好。
(2)gb18030字符集
在MySQL中,gb18030与中国国标GB18030信息技术编码相对应,是中国的官方字符集。
MySQL支持很多其他地区的字符集,限于篇幅,这里不再进行描述,读者可参考官方文档进行深入研究。
3.3.11 设置错误消息语言
默认情况下,mysqld产生的错误消息为英文,但可以转化成其他语言。服务器根据以下规则确定错误消息的语言。
(1)根据两个系统变量lc_messages_dir和lc_messages(lc_messages规定要转化的语言)。假设使用如下命令启动服务:
mysqld --lc_messages_dir=/usr/share/mysql --lc_messages=fr_FR
这种情况下,mysqld将fr_FR映射成法语,在/usr/share/mysql/french目录下寻找错误日志。
(2)如果在刚才构造的目录中找不到消息文件,服务器就会忽略lc_messages的值,只使用lc_messages_dir的值查找。
(3)如果服务器找不到配置的消息文件,就会向错误日志中以默认的英文写入消息。
lc_messages_dir系统变量只能在服务启动时被初始化,在运行时只读。lc_messages在服务启动时被初始化,运行期间也可以被更改。所以,通过设置会话变量lc_messages的值,客户端可修改错误消息的语言。例如,服务器以fr_FR作为错误消息语言,客户端可执行如下命令更改语言:
SET lc_messages = 'en_US';
3.3.12 添加字符集
字符集可根据复杂程度分为两种:简单字符集和复杂字符集。如果字符集不需要特殊字符,排序程序也不需要多字节支持,可视为简单字符集;如果字符集需要以上其中任何一个功能,就视为复杂字符集。
添加新字符集必须有MySQL源分布,然后根据以下步骤添加新的字符集。在以下描述中,MYSET代表想要添加的字符集名称。
第一步,添加<charset>元素到sql/share/charsets/Index.xml文件中,可使用已有的文件内容作为参考。latin1字符集的<charset>元素列表如下所示:
<charset name="latin1"> <family>Western</family> <description>cp1252 West European</description> ... <collation name="latin1_swedish_ci" id="8" order="Finnish, Swedish"> <flag>primary</flag> <flag>compiled</flag> </collation> <collation name="latin1_danish_ci" id="15" order="Danish"/> ... <collation name="latin1_bin" id="47" order="Binary"> <flag>binary</flag> <flag>compiled</flag> </collation> ... </charset>
<charset>元素必须列出字符集所有的排序,至少包含一个二进制排序和一个默认排序。默认排序通常以general_ci结尾。
必须给每一个排序分配唯一的id编号。1024到2047是为用户自定义保留的id编号。查询目前已用的最大id,使用如下语句:
SELECT MAX(ID) FROM INFORMATION_SCHEMA.COLLATIONS;
第二步,取决于要添加的字符集是简单的还是复杂的。简单字符集只需要一个配置文件,而复杂字符集需要定义排序函数或多字节函数的C源码文件。
(1)对简单字符集来说,在sql/share/charsets目录下创建配置文件MYSET.xml,描述字符集的属性,文件格式可参考latin1.xml。该文件的语法非常简单:
①注释和普通的XML注释相同。
②<map>数组元素的内容以任意数量的空格隔开。
③map>数组元素内的每个单词都是十六进制的数字。
④<ctype>元素的<map>数组元素有257个字。其他的<map>数组元素有256个字。
⑤对Index.xml中<charset>元素列出的每个排序,MYSET.xml必须包含<collation>元素定义字符排序。
(2)对于复杂的字符集,创建描述字符集属性的C源文件,并定义必要的操作程序:
①在字符串目录下创建ctype-MYSET.c文件。文件中的数组命名必须类似ctype_MYSET、to_lower_MYSET等。
②对于Index.xml中<charset>元素中的每个<collation>元素,ctype-MYSET.c文件必须提供排序的实现。
第三步,修改配置信息。
(1)编辑mysys/charset-def.c,为新字符集注册排序。
将以下内容加入声明部分:
#ifdef HAVE_CHARSET_MYSET extern CHARSET_INFO my_charset_MYSET_general_ci; extern CHARSET_INFO my_charset_MYSET_bin; #endif Add these lines to the “registration” section: #ifdef HAVE_CHARSET_MYSET add_compiled_collation(&my_charset_MYSET_general_ci); add_compiled_collation(&my_charset_MYSET_bin); #endif
(2)如果字符集使用ctype-MYSET.c,修改strings/CMakeLists.txt,把ctype-MYSET.c加到STRINGS_SOURCES变量的定义中。
(3)修改cmake/character_sets.cmake,按照字母顺序排列,分别将MYSET加入CHARSETS_AVAILABLE和CHARSETS_COMPLEX的值中。
第四步,配置完成后,重新编译,然后测试。
3.3.13 将排序规则添加到字符集
排序是一系列的规则,定义了如何比较和分类字符串。排序根据权重分类字符。字符集中的每个字符对应一个权重。拥有相同权重的字符相等,权重不同的字符根据相关权重比较。
WEIGHT_STRING()函数可以用来查看字符的权重,该函数返回的是二进制权重,可使用HEX(WEIGHT_STRING(str))函数以打印的形式显示结果,如图3-28所示。

图3-28 查看权重
图3-28显示出在非二进制不区分大小的字符串中字母的权重不区分大小写,但在二进制字符中区分。
添加排序的步骤如下:
(1)选择一个排序id。
(2)添加配置信息,包括命名排序以及描述字符排序规则。
(3)重启服务器。
(4)验证排序已添加。
这里添加的排序只是不需要重新编译的排序,需要编译的添加步骤请参考3.3.12小节。
提示
如果修改现有排序,就可能会影响使用该排序的索引,所以要重建相关索引。
3.3.14 字符集配置
启动服务器时,可使用--character-set-server和--collation-server选项修改默认的字符集和排序。
对于客户端,可强制其使用明确的字符集,配置如下所示:
[client] default-character-set=charset_name
如果系统变量character_set_system和character_set_server或character_set_client变量不同,并且进行了手动加入字符操作,客户端会报错,可以在启动客户端时使用default-character-set=system_character_set配置以解决该问题。
3.3.15 MySQL服务器区域设置支持
系统变量lc_time_names指定的区域决定了相关的显示语言。
lc_time_names变量影响DATE_FORMAT()、DAYNAME()和MONTHNAME()函数的输出,不会影响STR_TO_DATE()或GET_FORMAT()函数。
区域名称以及包含的语言和区域标识由IANA(互联网号码分配当局)提供。系统区域设置默认为'en_US',但可在服务器启动时修改。如果拥有系统变量管理员或超级管理员的权限也可以通过设置GLOBAL的值进行修改。任何客户端都可查验lc_time_names的值,也可以通过设置会话值改变自身连接的区域。