Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  Character Sets, Collations, Unicode  /  Connection Character Sets and Collations

12.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_clientcharacter_set_resultscharacter_set_connection系统变量设置为字符集,并将collation_connection设置为字符集默认排序规则。实际上,服务器执行了等同于SET NAMES操作。

如果服务器不支持请求的字符集或排序规则,它将使用服务器字符集和排序规则来配置连接。关于这个 fallback 行为的详细信息,请参见连接字符集错误处理

mysqlmysqladminmysqlcheckmysqlimportmysqlshow 客户端程序确定使用的默认字符集如下:

  • 在缺少其他信息的情况下,每个客户端都使用编译时的默认字符集,通常是utf8mb4

  • 每个客户端可以根据操作系统设置自动检测字符集,例如 Unix 系统中的 LANGLC_ALL 环境变量值,或者 Windows 系统中的代码页设置。对于支持 locale 的系统,客户端使用它来设置默认字符集,而不是使用编译时的默认字符集。例如,将 LANG 设置为 ru_RU.KOI8-R 则使用 koi8r 字符集。因此,用户可以在环境中配置 locale,以便 MySQL 客户端使用。

    如果 OS 字符集没有精确匹配的映射,客户端将使用编译时的默认字符集。如果客户端不支持匹配字符集,它将使用编译时的默认字符集。例如,utf8utf-8 映射到 utf8mb4,而 ucs2 不支持连接字符集,所以它映射到编译时的默认字符集。

    C 应用程序可以使用 OS 设置来自动检测字符集,通过在连接服务器前调用mysql_options()如下方式:

    mysql_options(mysql,
                  MYSQL_SET_CHARSET_NAME,
                  MYSQL_AUTODETECT_CHARSET_NAME);
  • 每个客户端都支持一个 --default-character-set 选项,允许用户指定字符集,以便覆盖客户端其他方式确定的默认字符集。

    Note

    某些字符集不能用作客户端字符集。使用--default-character-set时,会产生错误。见不允许的客户端字符集

使用mysql 客户端,可以每次连接服务器时,明确执行一个SET NAMES语句(见客户端程序连接字符集配置)。为了更方便地实现相同的结果,可以在选项文件中指定字符集。例如,以下选项文件设置,每次调用mysql时,将三个连接相关的字符集系统变量都设置为koi8r

[mysql]
default-character-set=koi8r

如果您使用mysql 客户端,自动重连功能(不推荐)时,建议使用charset命令,而不是SET NAMES。例如:

mysql> charset koi8r
Charset changed

命令charset发出SET NAMES语句,同时也将mysql在重新连接后使用的默认字符集。

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

连接字符集配置语句

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

Note

某些字符集不能用作客户端字符集。使用SET NAMESSET CHARACTER SET时,会出现错误。请参阅不允许的客户端字符集

示例:假设column1被定义为CHAR(5) CHARACTER SET latin2。如果您没有说SET NAMESSET CHARACTER SETSELECT column1 FROM t,服务器将使用客户端连接时指定的字符集发送所有值。反之,如果您在发出SELECT语句前说SET NAMES 'latin1'SET CHARACTER SET 'latin1',服务器就在发送结果时将latin2值转换为latin1。对于不在两个字符集中的字符可能会丢失。

尝试使用不适当的连接字符集或排序规则可能会产生错误,或者使服务器在给定的连接中回退到默认字符集和排序规则。这部分描述了配置连接字符集时可能出现的问题,这些问题可以在建立连接时或更改连接中的字符集时出现。

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

$> 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/)

如果您指定了客户端认识但服务器不认识的字符集,服务器回退到默认字符集和排序规则。假设服务器配置使用latin1latin1_swedish_ci作为默认值,而服务器不认可gb18030为有效字符集。客户端指定--default-character-set=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 |
+----------------------+-------------------+

您可以看到连接系统变量已经设置为反映了字符集和排序规则latin1latin1_swedish_ci。这是因为服务器无法满足客户端字符集请求,于是回退到默认值。

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

同样问题也会发生在客户端告诉服务器使用一个服务器认识的字符集,但是客户端默认排序规则在服务器端不知道的情况下。

在已经建立的连接中,客户端可以使用SET NAMESSET CHARACTER SET请求更改连接字符集和排序规则。

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

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'
Tip

想要验证客户端请求字符集是否被服务器认可的客户端,可以在连接后执行以下语句并检查结果是否是预期的字符集:

SELECT @@character_set_client;