一个”连接”是客户端程序连接到服务器时开始与服务器交互的会话时所生成的内容。客户端通过会话连接发送SQL语句,例如查询。服务器通过连接将响应(如结果集或错误消息)发送回客户机。
一些字符集和排序系统变量与客户机与服务器的交互有关。其中一些已经在前面的章节中提到过:
的
character_set_server
而且collation_server
系统变量表示服务器字符集和排序规则。看到第10.3.2节,“服务器字符集和排序规则”.的
character_set_database
而且collation_database
系统变量表示默认数据库的字符集和排序规则。看到第10.3.3节“数据库字符集和排序规则”.
在处理客户机和服务器之间的连接时,还涉及到其他字符集和排序系统变量。每个客户机都有特定于会话的与连接相关的字符集和排序系统变量。这些会话系统变量值在连接时初始化,但是可以在会话中更改。
关于字符集和客户端连接排序处理的几个问题可以用系统变量来回答:
语句离开客户端时是什么字符集?
服务器接收
character_set_client
系统变量为客户端发送语句的字符集。请注意某些字符集不能用作客户端字符集。看到不允许的客户端字符集.
服务器接收到语句后应该将其转换为什么字符集?
要确定这一点,服务器使用
character_set_connection
而且collation_connection
系统变量:服务器将客户机发送的语句转换为
character_set_client
来character_set_connection
.例外:对于有引入器的字符串字面量_utf8mb4
或_latin2
,引入器确定字符集。看到第10.3.8节“字符集介绍器”.collation_connection
对于字面值字符串的比较很重要。对于字符串与列值的比较,collation_connection
没关系,因为列有自己的排序规则,排序规则具有更高的优先级(参见第10.8.4节,“表达式中的排序强制力”).
在将查询结果发送回客户端之前,服务器应该将查询结果转换为什么字符集?
的
character_set_results
系统变量:服务器向客户端返回查询结果的字符集。这包括结果数据(如列值)、结果元数据(如列名)和错误消息。要告诉服务器不执行结果集或错误消息的转换,请设置
character_set_results
来零
或二进制
:SET character_set_results = NULL;SET character_set_results = binary;
有关字符集和错误消息的详细信息,请参见第10.6节,“错误消息字符集”.
要查看应用于当前会话的字符集和排序系统变量的值,使用以下语句:
SELECT * FROM performance_schema。WHERE VARIABLE_NAME IN ('character_set_client', 'character_set_connection', 'character_set_results', 'collation_connection')
下面的简单语句也显示连接变量,但也包括其他相关变量。它们可能是有用的所有字符集和整理系统变量:
显示像'character\_set\_%'这样的会话变量;显示类似“collation\_%”的会话变量;
客户端可以微调这些变量的设置,或者依赖于默认值(在这种情况下,您可以跳过本节的其余部分)。如果不使用默认值,则必须更改字符设置对于到服务器的每个连接。
的character_set_client
系统变量不能设置为某些字符集:
Ucs2 utf16 utf16le utf32
试图使用这些字符集中的任何一个作为客户端字符集都会产生一个错误:
SET character_set_client = 'ucs2';错误1231(42000):变量'character_set_client'不能设置为'ucs2'值
如果在以下上下文中使用这些字符集中的任何一个,都将导致尝试设置,则会发生相同的错误character_set_client
命名字符集:
的
——default-character-set =
命令选项用于MySQL客户端程序,如mysql而且mysqladmin.charset_name
当客户机连接到服务器时,它指示它希望使用哪个字符集与服务器通信。(实际上,客户端指示该字符集的默认排序规则,服务器可以从中确定字符集。)服务器使用此信息设置character_set_client
,character_set_results
,character_set_connection
系统变量到字符集,和collation_connection
到字符集默认排序规则。实际上,服务器执行的相当于组名称
操作。
如果服务器不支持所请求的字符集或排序规则,它将退回到使用服务器字符集和排序规则来配置连接。有关此回退行为的更多详细信息,请参见连接字符集错误处理.
的mysql,mysqladmin,mysqlcheck,mysqlimport,mysqlshow客户端程序确定使用的默认字符集如下所示:
在没有其他信息的情况下,每个客户机通常使用编译后的默认字符集
utf8mb4
.的值等操作系统设置的基础上,每个客户机可以自动检测要使用的字符集
朗
或LC_ALL
Unix系统上的locale环境变量或Windows系统上的代码页设置。对于可以从操作系统获得区域设置的系统,客户端使用它来设置默认字符集,而不是使用编译后的默认字符集。例如,设置朗
来ru_RU。KOI8-R
导致koi8r
要使用的字符集。因此,用户可以在其环境中配置本地语言环境,以供MySQL客户机使用。如果没有精确的匹配,操作系统字符集将映射到最接近的MySQL字符集。如果客户端不支持匹配的字符集,则使用编译后的默认值。例如,
use utf8
而且utf - 8
映射到utf8mb4
,ucs2
不支持作为连接字符集,因此它映射到编译后的默认值。C应用程序可以通过调用使用基于操作系统设置的字符集自动检测
mysql_options ()
连接服务器前请执行以下操作:mysql_options (mysql MYSQL_SET_CHARSET_NAME MYSQL_AUTODETECT_CHARSET_NAME);
每个客户端支持
——default-character-set
选项,该选项允许用户显式指定字符集以覆盖客户机其他方式确定的任何默认值。请注意某些字符集不能用作客户端字符集。试图用它们
——default-character-set
产生一个错误。看到不允许的客户端字符集.
与mysql客户端,要使用与默认字符集不同的字符集,可以显式执行组名称
语句(请参见客户端程序连接字符集配置).要更容易地实现相同的结果,请在选项文件中指定字符集。例如,以下选项文件设置将更改设置为的三个与连接相关的字符集系统变量koi8r
每次你调用mysql:
(mysql) default-character-set = koi8r
如果您正在使用mysql如果客户端启用了自动重新连接(不推荐),则最好使用字符集
命令而不是组名称
.例如:
mysql>字符集koi8r字符集更改
的字符集
命令的问题组名称
语句,并更改默认字符集thatmysql在连接断开后重新连接时使用。
在配置客户机程序时,还必须考虑它们在其中执行的环境。看到第10.5节“配置应用程序字符集和排序规则”.
建立连接后,客户端可以更改当前会话的字符集和排序系统变量。这些变量可以使用集
语句,但是有两个更方便的语句影响连接相关的字符集系统变量作为一个组:
组名称”
charset_name
(核对的collation_name
']组名称
表示客户端向服务器发送SQL语句时使用的字符集。因此,设置名称“cp1251”
告诉服务器,”来自此客户机的未来传入消息采用字符集cp1251
.”它还指定服务器将结果发送回客户机时应该使用的字符集。(例如,它指示列值使用什么字符集选择
生成结果集的语句。)一个
组名称”
语句等价于以下三个语句:charset_name
'设置character_set_client =charset_name;设置character_set_results =charset_name;设置character_set_connection =charset_name;
设置
character_set_connection
来charset_name
也含蓄地集collation_connection
的默认排序规则charset_name
.没有必要显式地设置该排序规则。指定要使用的特定排序规则collation_connection
,添加一个核对
条款:组名称”charset_name“整理”collation_name'
字符集'
'charset_name
设置字符集
类似于组名称
但集character_set_connection
而且collation_connection
来character_set_database
而且collation_database
(如前所述,指示默认数据库的字符集和排序规则)。一个
设置字符集
语句等价于以下三个语句:charset_name
设置character_set_client =charset_name;设置character_set_results =charset_name;SET collation_connection = @@collation_database;
设置
collation_connection
也含蓄地集character_set_connection
与排序规则相关联的字符集(相当于执行SET character_set_connection = @@character_set_database
).不需要设置character_set_connection
明确。
某些字符集不能用作客户端字符集。试图用它们组名称
或设置字符集
产生一个错误。看到不允许的客户端字符集.
例子:假设column1
被定义为CHAR(5)字符集拉丁文
.如果你不说组名称
或设置字符集
,然后SELECT columnn1 FROM t
,服务器返回所有的值column1
使用客户端连接时指定的字符集。另一方面,如果你说设置名称“latin1”中的一个
或字符集'latin1'
在发出之前选择
语句时,服务器将转换latin2
值latin1
就在送回结果之前。对于不属于两个字符集的字符,转换可能是有损的。
试图使用不适当的连接字符集或排序规则会产生错误,或导致服务器退回到给定连接的默认字符集和排序规则。本节描述在配置连接字符集时可能出现的问题。这些问题可能发生在建立连接或更改已建立连接中的字符集时。
连接时间错误处理
有些字符集不能用作客户端字符集;看到不允许的客户端字符集.如果您指定的字符集有效但不允许作为客户端字符集,服务器将返回一个错误:
shell> mysql——default-character-set=ucs2 ERROR 1231(42000):变量'character_set_client'不能设置为'ucs2'的值
如果您指定的字符集客户端无法识别,则会产生一个错误:
错误2019 (HY000): Can't initialize Character set bogus(路径:/usr/local/mysql/share/charsets/Index.xml)
如果您指定的字符集客户机可以识别,而服务器不能识别,则服务器将退回到其默认字符集和排序规则。假设服务器配置为使用latin1
而且latin1_swedish_ci
作为它的默认值,它不承认gb18030
作为一个有效的字符集。指定一个客户端——default-character-set = gb18030
能够连接到服务器,但是生成的字符集不是客户端想要的:
显示“character\_set\_%”的会话变量+--------------------------+--------+ | Variable_name |值 | +--------------------------+--------+ | character_set_client | latin1 |中的一个| character_set_connection | latin1 |中的一个……| character_set_results | latin1 |…+--------------------------+--------+ mysql >显示会话变量如“collation_connection”;+----------------------+-------------------+ | Variable_name |值 | +----------------------+-------------------+ | collation_connection | latin1_swedish_ci | +----------------------+-------------------+
可以看到连接系统变量已设置为反映字符集和排序规则latin1
而且latin1_swedish_ci
.这是因为服务器无法满足客户端字符集请求而退回到其默认值。
在这种情况下,客户端不能使用它想要的字符集,因为服务器不支持它。客户端必须愿意使用不同的字符集,或者连接到支持所需字符集的不同服务器。
同样的问题发生在更微妙的上下文中:当客户机告诉服务器使用服务器识别的字符集,但服务器端不知道该字符集在客户机端的默认排序规则时。例如,当MySQL 8.0客户端想要使用utf8mb4
作为客户端字符集。指定一个客户端——default-character-set = utf8mb4
能够连接到服务器。然而,就像前面的例子一样,服务器返回到它的默认字符集和排序规则,而不是客户端请求的:
显示“character\_set\_%”的会话变量+--------------------------+--------+ | Variable_name |值 | +--------------------------+--------+ | character_set_client | latin1 |中的一个| character_set_connection | latin1 |中的一个……| character_set_results | latin1 |…+--------------------------+--------+ mysql >显示会话变量如“collation_connection”;+----------------------+-------------------+ | Variable_name |值 | +----------------------+-------------------+ | collation_connection | latin1_swedish_ci | +----------------------+-------------------+
为什么会出现这种情况?毕竟,utf8mb4
8.0客户机和5.7服务器都知道它,因此它们都能识别它。要理解这种行为,有必要理解当客户机告诉服务器它想使用哪个字符集时,它实际上是在告诉服务器该字符集的默认排序规则。因此,上述行为的发生是由多种因素共同作用的结果:
的默认排序规则
utf8mb4
MySQL 5.7和MySQL 8.0不同(utf8mb4_general_ci
为5.7,utf8mb4_0900_ai_ci
为8.0)。当8.0客户端请求的字符集
utf8mb4
,它发送给服务器的是默认的8.0utf8mb4
排序;也就是说,utf8mb4_0900_ai_ci
.utf8mb4_0900_ai_ci
是MySQL 8.0才实现的,所以5.7服务器不识别它。因为5.7服务器不识别
utf8mb4_0900_ai_ci
,它不能满足客户端字符集请求,并退回到其默认字符集和排序规则(latin1
而且latin1_swedish_ci
).
在这种情况下,客户端仍然可以使用utf8mb4
通过发出一个设置名称“utf8mb4”
连接后声明。生成的排序规则是5.7默认的utf8mb4
排序;也就是说,utf8mb4_general_ci
.的排序utf8mb4_0900_ai_ci
,它无法实现这一点,因为服务器不识别该排序规则。客户必须愿意使用不同的utf8mb4
或从MySQL 8.0或更高版本连接到服务器。
运行时错误处理
在已建立的连接中,客户端可以请求更改连接字符集和排序规则组名称
或设置字符集
.
有些字符集不能用作客户端字符集;看到不允许的客户端字符集.如果您指定的字符集有效但不允许作为客户端字符集,服务器将返回一个错误:
mysql>设置名称为ucs2;错误1231(42000):变量'character_set_client'不能设置为'ucs2'值
如果服务器不识别字符集(或排序规则),它会产生一个错误:
mysql> SET NAMES 'bogus';错误1115(42000):未知字符集:'bogus' mysql> set NAMES 'utf8mb4' COLLATE 'bogus';错误1273 (HY000):未知排序:'bogus'
客户端想要验证其请求的字符集是否被服务器接受,在连接并检查结果是否为预期的字符集后,可以执行以下语句:
选择@@character_set_client;