Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 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操作。

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

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

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

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

    操作系统字符集将映射到 MySQL 字符集的最近匹配项,如果没有精确匹配。如果客户端不支持匹配的字符集,它将使用编译的默认值。例如,utf8utf-8 映射到 utf8mb4,而 ucs2 不支持作为连接字符集,因此映射到编译的默认值。

    C 应用程序可以通过在连接到服务器之前调用 mysql_options() 来基于操作系统设置进行字符集自动检测:

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

    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 节,“配置应用程序字符集和排序”

连接字符集配置的 SQL 语句

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

  • SET NAMES 'charset_name' [COLLATE 'collation_name']

    SET NAMES 指示客户端使用什么字符集将 SQL 语句发送到服务器。因此,SET NAMES 'cp1251' 告诉服务器,从这个客户端来的未来入站消息都是字符集 cp1251 的。 它还指定了服务器应该使用的字符集,以便将结果发送回客户端。(例如,它指定了使用 SELECT 语句生成结果集时的字符集。)

    一个 SET NAMES 'charset_name' 语句等同于这三个语句:

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

    character_set_connection 设置为 charset_name 也隐式地将 collation_connection 设置为 charset_name 的默认排序。无需明确设置该排序。要指定特定的排序用于 collation_connection,请添加一个 COLLATE 子句:

    SET NAMES 'charset_name' COLLATE 'collation_name'
  • SET CHARACTER SET 'charset_name'

    SET 字符集SET NAMES 相似,但设置 character_set_connectioncollation_connectioncharacter_set_databasecollation_database(如前所述,表示默认数据库的字符集和排序规则)。

    一个 SET 字符集 charset_name 语句等同于以下三个语句:

    SET character_set_client = charset_name;
    SET 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

Note

一些字符集不能用作客户端字符集。尝试使用它们与 SET NAMESSET 字符集 将产生错误。请参阅 不可用的客户端字符集

示例:假设 column1 被定义为 CHAR(5) CHARACTER SET latin2。如果您不说 SET NAMESSET CHARACTER SET,那么对于 SELECT column1 FROM t,服务器将使用客户端连接时指定的字符集发送所有的 column1 值。另一方面,如果您在发出 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。这是因为服务器无法满足客户端字符集请求,fallback 到其默认值。

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

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

运行时错误处理

在已建立的连接中,客户端可以使用 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

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

SELECT @@character_set_client;