# 10.4 连接字符集和排序规则

“连接”是客户端程序在连接到服务器时所做的,以开始与服务器交互的会话。客户端通过会话连接发送 SQL 语句,例如查询。服务器通过连接将响应(例如结果集或错误消息)发送回客户端。

# 连接字符集和排序规则系统变量

几个字符集和排序规则系统变量与客户端与服务器的交互有关。其中一些已经在前面的章节中提到过:

SELECT * FROM performance_schema.session_variables
WHERE VARIABLE_NAME IN (
'character_set_client', 'character_set_connection',
'character_set_results', 'collation_connection'
) ORDER BY VARIABLE_NAME;

以下更简单的语句也显示连接变量,但也包括其他相关变量。它们可能很有用全部字符集和排序规则系统变量:

SHOW SESSION VARIABLES LIKE 'character\_set\_%';
SHOW SESSION VARIABLES LIKE 'collation\_%';

客户端可以微调这些变量的设置,或者依赖于默认值(在这种情况下,您可以跳过本节的其余部分)。如果不使用默认值,则必须更改字符设置对于与服务器的每个连接。

# 不允许的客户端字符集

character_set_client系统变量不能设置为某些字符集:

ucs2
utf16
utf16le
utf32

尝试使用任何这些字符集作为客户端字符集会产生错误:

mysql> SET character_set_client = 'ucs2';
ERROR 1231 (42000): Variable 'character_set_client'
can't be set to the value of 'ucs2'

如果在以下上下文中使用任何这些字符集,则会发生相同的错误,所有这些都会导致尝试设置character_set_client到命名字符集:

# 客户端程序连接字符集配置

当客户端连接到服务器时,它会指示它想要使用哪个字符集与服务器通信。(实际上,客户端指示该字符集的默认排序规则,服务器可以从中确定字符集。)服务器使用此信息来设置character_set_client,字符集结果,字符集连接字符集的系统变量,以及collat​​ion_connection到字符集默认排序规则。实际上,服务器执行相当于设置名称手术。

如果服务器不支持请求的字符集或排序规则,它会回退到使用服务器字符集和排序规则来配置连接。有关此回退行为的更多详细信息,请参阅连接字符集错误处理.

mysql,mysql管理员,mysql检查,mysql导入, 和mysqlshow客户端程序确定要使用的默认字符集如下:

  • 在没有其他信息的情况下,每个客户端都使用编译进来的默认字符集,通常utf8mb4.

  • 每个客户端都可以根据操作系统设置自动检测要使用的字符集,例如要么LC_ALLUnix 系统上的语言环境变量或 Windows 系统上的代码页设置。对于可以从 OS 获得区域设置的系统,客户端使用它来设置默认字符集,而不是使用编译后的默认值。例如,设置ru_RU.KOI8-R导致锦鲤8r要使用的字符集。因此,用户可以在他们的环境中配置区域设置以供 MySQL 客户端使用。

    如果没有完全匹配,则 OS 字符集映射到最接近的 MySQL 字符集。如果客户端不支持匹配的字符集,它使用编译的默认值。例如,utf8utf-8映射到utf8mb4, 和ucs2不支持作为连接字符集,因此它映射到编译的默认值。

    C 应用程序可以通过调用来使用基于操作系统设置的字符集自动检测mysql_options() (opens new window)连接服务器前如下:

    mysql_options(mysql,
                  MYSQL_SET_CHARSET_NAME,
                  MYSQL_AUTODETECT_CHARSET_NAME);
    
  • 每个客户端支持一个--默认字符集选项,它使用户能够显式指定字符集以覆盖客户端以其他方式确定的任何默认值。

    笔记

    某些字符集不能用作客户端字符集。尝试将它们与--默认字符集产生错误。看不允许的客户端字符集.

    随着mysql客户端,要使用与默认字符集不同的字符集,您可以显式执行设置名称每次连接到服务器时的语句(请参阅客户端程序连接字符集配置)。要更轻松地完成相同的结果,请在选项文件中指定字符集。例如,以下选项文件设置将三个与连接相关的字符集系统变量设置为锦鲤8r每次调用mysql

[mysql]
default-character-set=koi8r

如果您正在使用mysql启用自动重新连接的客户端(不推荐),最好使用字符集命令而不是设置名称.例如:

mysql> charset koi8r
Charset changed

字符集命令发出一个设置名称语句,并且还更改了默认字符集mysql在连接断开后重新连接时使用。

在配置客户端程序时,您还必须考虑它们执行的环境。看第 10.5 节,“配置应用程序字符集和排序规则”.

# 连接字符集配置的 SQL 语句

建立连接后,客户端可以更改当前会话的字符集和排序规则系统变量。这些变量可以单独使用语句,但有两个更方便的语句将连接相关的字符集系统变量作为一个组来影响:

  • 设置名称'*字符集名称*' [整理'*collat​​ion_name*']

    设置名称指示客户端用于向服务器发送 SQL 语句的字符集。因此,设置名称“cp1251”告诉服务器,“将来从这个客户端传入的消息都是字符集cp1251“它还指定了服务器应用于将结果发送回客户端的字符集。(例如,如果使用选择生成结果集的语句。)

    A.定名*charset_名称*'语句相当于这三种语句:

    SET character_set_client = charset_name;
    SET character_set_results = charset_name;
    SET character_set_connection = charset_name;
    

    背景字符集连接到*charset_名称还隐式设置校对连接到的默认排序规则charset_名称*。没有必要显式设置该排序规则。指定要用于的特定排序规则校对连接,添加一个整理条款:

    SET NAMES 'charset_name' COLLATE 'collation_name'
    
  • 设置字符集'*charset_名称*'

    集合字符集类似于定名但是设置字符集连接校对连接字符集数据库整理数据库(如前所述,它指示默认数据库的字符集和排序规则)。

    A.集合字符集*charset_名称*语句相当于这三种语句:

    SET character_set_client = charset_name;
    SET character_set_results = charset_name;
    SET collation_connection = @@collation_database;
    

    背景校对连接还隐式设置字符集连接与排序规则关联的字符集(相当于执行设置字符集连接=@@character\u SET\u数据库).没有必要设置字符集连接明确地

笔记

某些字符集不能用作客户端字符集。试图将它们用于定名集合字符集产生一个错误。看见不允许的客户端字符集.

假设专栏1定义为字符(5)字符集2.如果你不说定名集合字符集,那么从t中选择column1,服务器会发回专栏1使用客户端连接时指定的字符集。另一方面,如果你说设置名称“latin1”设置字符集“latin1”在发布选择语句,服务器将拉丁语2价值观拉丁语1就在返回结果之前。对于不在两个字符集中的字符,转换可能会有损。

# 连接字符集错误处理

尝试使用不适当的连接字符集或排序规则可能会产生错误,或导致服务器退回到给定连接的默认字符集和排序规则。本节介绍配置连接字符集时可能出现的问题。在建立连接或更改已建立连接中的字符集时,可能会出现这些问题。

# 连接时间错误处理

某些字符集不能用作客户端字符集;看见不允许的客户端字符集。如果指定了有效但不允许作为客户端字符集的字符集,服务器将返回错误:

$> mysql --default-character-set=ucs2
ERROR 1231 (42000): Variable 'character_set_client' can't be set to
the value of 'ucs2'

如果指定了客户端无法识别的字符集,则会产生错误:

$> mysql --default-character-set=bogus
mysql: Character set 'bogus' is not a compiled character set and is
not specified in the '/usr/local/mysql/share/charsets/Index.xml' file
ERROR 2019 (HY000): Can't initialize character set bogus
(path: /usr/local/mysql/share/charsets/)

如果指定了一个客户机可以识别但服务器不能识别的字符集,则服务器会返回其默认字符集和排序规则。假设服务器配置为使用拉丁语1拉丁语瑞典语作为它的默认值,它不承认gb18030作为有效的字符集。指定--默认字符集=gb18030能够连接到服务器,但生成的字符集不是客户端想要的:

mysql> SHOW SESSION VARIABLES LIKE 'character\_set\_%';
+--------------------------+--------+
| Variable_name            | Value  |
+--------------------------+--------+
| character_set_client     | latin1 |
| character_set_connection | latin1 |
...
| character_set_results    | latin1 |
...
+--------------------------+--------+
mysql> SHOW SESSION VARIABLES LIKE 'collation_connection';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
+----------------------+-------------------+

您可以看到,已将连接系统变量设置为反映拉丁语1拉丁语瑞典语。发生这种情况的原因是服务器无法满足客户端字符集请求,并返回其默认值。

在这种情况下,客户端无法使用它想要的字符集,因为服务器不支持它。客户端必须愿意使用不同的字符集,或者连接到支持所需字符集的不同服务器。

同样的问题也发生在更微妙的上下文中:当客户端告诉服务器使用服务器可以识别的字符集,但服务器端不知道该字符集在客户端的默认排序规则时。例如,当MySQL 8.0客户端希望使用utf8mb4作为客户端字符集。指定--默认字符集=utf8mb4能够连接到服务器。但是,与前一个示例一样,服务器返回到其默认字符集和排序规则,而不是客户端所请求的:

mysql> SHOW SESSION VARIABLES LIKE 'character\_set\_%';
+--------------------------+--------+
| Variable_name            | Value  |
+--------------------------+--------+
| character_set_client     | latin1 |
| character_set_connection | latin1 |
...
| character_set_results    | latin1 |
...
+--------------------------+--------+
mysql> SHOW SESSION VARIABLES LIKE 'collation_connection';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
+----------------------+-------------------+

为什么会发生这种情况?毕竟utf8mb48.0客户端和5.7服务器都知道它,所以它们都能识别它。为了理解这种行为,有必要理解,当客户机告诉服务器它想要使用哪个字符集时,它实际上会告诉服务器该字符集的默认排序规则。因此,上述行为的发生是多种因素共同作用的结果:

  • 的默认排序规则utf8mb4MySQL 5.7和8.0之间的差异(utf8mb4_通用_ci对于5.7,utf8mb4_0900_ai_ci8.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,它无法满足客户端字符集请求,并返回到其默认字符集和排序规则(拉丁语1拉丁语瑞典语).

    在这种情况下,客户端仍然可以使用utf8mb4通过发布设置名称“utf8mb4”连接后的声明。由此产生的排序规则是5.7默认值utf8mb4校勘;就是,utf8mb4_通用_ci.如果客户另外需要utf8mb4_0900_ai_ci,它无法实现这一点,因为服务器无法识别该排序规则。客户必须愿意使用不同的utf8mb4排序规则,或从MySQL 8.0或更高版本连接到服务器。

# 运行时错误处理

在已建立的连接中,客户端可以请求更改连接字符集和排序规则定名集合字符集.

某些字符集不能用作客户端字符集;看见不允许的客户端字符集。如果指定了有效但不允许作为客户端字符集的字符集,服务器将返回错误:

mysql> SET NAMES 'ucs2';
ERROR 1231 (42000): Variable 'character_set_client' can't be set to
the value of 'ucs2'

如果服务器无法识别字符集(或排序规则),则会产生错误:

mysql> SET NAMES 'bogus';
ERROR 1115 (42000): Unknown character set: 'bogus'

mysql> SET NAMES 'utf8mb4' COLLATE 'bogus';
ERROR 1273 (HY000): Unknown collation: 'bogus'

提示

如果客户端希望验证其请求的字符集是否已被服务器接受,则可以在连接并检查结果是否为预期的字符集后执行以下语句:

SELECT @@character_set_client;