文档首页
MySQL 8.4 参考手册
相关文档 下载本手册

MySQL 8.4 参考手册  /  字符集、排序规则、Unicode  /  连接字符集和排序规则

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_ALL 本地环境变量的值,或 Windows 系统上的代码页设置。对于操作系统上提供本地设置的系统,客户端使用它来设置默认字符集,而不是使用编译后的默认字符集。例如,将 LANG 设置为 ru_RU.KOI8-R 会导致使用 koi8r 字符集。因此,用户可以在其环境中配置本地设置,以便 MySQL 客户端使用。

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

    C 应用程序可以通过调用 mysql_options() 来使用基于操作系统设置的字符集自动检测,如下所示,在连接到服务器之前

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

    注意

    某些字符集不能用作客户端字符集。尝试使用 --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 NAMESSET CHARACTER SET 使用它们会导致错误。请参阅 不允许的客户端字符集

例如:假设 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 的字符集和排序规则。这是因为服务器无法满足客户端字符集请求,因此回退到其默认值。

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

当客户端告诉服务器使用服务器可以识别但客户端默认排序规则在服务器端未知的字符集时,也会出现同样的问题。

运行时错误处理

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

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

SELECT @@character_set_client;