MySQL: Connection Character Sets and Collations

character_set_server 
collation_server
character_set_database
collation_database

 

character_set_client
character_set_results


character_set_connection <===character_set_client
collation_connection

 

skip-character-set-client-handshake

 

 client (character_set_client) -----> character_set_connection -------> mysqld  ------> client(character_set_results)

 

存在三次编码转换过程:

1)mysql client 使用 character_set_client编码的字符------> character_set_connection 编码字符

    ------> mysqld :这里需要从 character_set_connection 编码格式二进制流解码成 字符,然后使用 character_set_server/character_set_database 对字符进行再次编码,生成二进制流,存储时,就是存储再次编码的二进制流数据。

2)读取数据时,会使用 character_set_server/character_set_database 对读取到的二级制流进行 解码成 字符,然后使用 character_set_results 对字符进行二次编码,生成二进制流,发给 mysql client.

所以 使用 set names 'xxx' 命令,结合 character_set_server 参数,可以将 整个过程的 字符集设置成相同的,就不会存在编码转换的过程。

 1.-

 2.-

  在处理客户端和服务器之间的连接的流量时涉及附加的字符集和校对系统变量。

  每个客户端都有特定于会话的连接相关字符集和校对系统变量。

  这些会话系统变量值在连接时初始化,但可以在会话中更改。

 3.-

  • 服务器收到语句后应该将语句翻译成什么字符集?

    要确定这一点,服务器使用 character_set_connection 和collation_connection 系统变量:

 4.-

  • 在将查询结果发送回客户端之前,服务器应该将哪些字符集转换为结果?

  character_set_results 系统变量指示在其中服务器查询结果返回到客户端的字符集。这包括结果数据,如列值,结果元数据(如列名称)和错误消息。

  要告诉服务器不执行结果集或错误消息的转换,请设置 character_set_results为 NULLbinary

 5.-

  • 要查看适用于当前会话的字符集和排序规则系统变量的值,请使用以下语句:
 
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;

6.-

  • C应用程序可以mysql_options()在连接到服务器之前通过以下方式调用根据操作系统设置使用字符集自动检测 

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

 7.-

  • 使用mysql客户端,要使用与默认值不同的字符集,SET NAMES每次连接到服务器时都可以显式执行 语句(请参阅客户端程序连接字符集配置)。要更轻松地完成相同的结果,请在选项文件中指定字符集。例如,以下选项文件设置更改koi8r每次调用mysql设置的三个与连接相关的字符集系统变量
 
    [mysql]
    default-character-set=koi8r

8.-
  • 如果您正在使用启用了自动重新连接mysql客户端(不建议这样做),则最好使用charset命令而不是SET NAMES例如:
  mysql> charset koi8r
  Charset changed

    该charset命令发出一个 SET NAMES语句,并且还更改mysql 在连接断开后重新连接时使用的默认字符集。

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

 9.-

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

10.-

  • SET CHARACTER SET 'charset_name' 一个语句相当于这三个语句:
    SET character_set_client = charset_name;
    SET character_set_results = charset_name;
    SET collation_connection = @@collation_database;

11.-

  • utf8mb4MySQL 5.7和8.0之间 的默认排序规则不同(utf8mb4_general_ci对于5.7,utf8mb4_0900_ai_ci对于8.0)。

  • 当8.0客户端请求一个字符集时 utf8mb4,它发送给服务器的是默认的8.0 utf8mb4排序规则; 也就是说utf8mb4_0900_ai_ci

  • utf8mb4_0900_ai_ci 仅在MySQL 8.0中实现,因此5.7服务器无法识别它。

  • 由于5.7服务器无法识别 utf8mb4_0900_ai_ci,因此无法满足客户端字符集请求,并回退到其默认字符集和排序规则(latin1和 latin1_swedish_ci)。

在这种情况下,客户端仍然可以在连接后utf8mb4通过发出SET NAMES 'utf8mb4'语句来使用 得到的排序规则是5.7默认utf8mb4 排序规则; 就是这样utf8mb4_general_ci如果客户端另外需要进行整理utf8mb4_0900_ai_ci,则无法实现该目标,因为服务器无法识别该整理。客户端必须愿意使用不同的 utf8mb4排序规则,或者从MySQL 8.0或更高版本连接到服务器。

 12.-

在MySQL 4.0版中, 服务器和客户端都有一个“ 全局 ”字符集,并决定服务器管理员使用哪个字符。这从MySQL 4.1版开始改变。现在发生的是“ 握手 ”,如 第10.4节“连接字符集和排序规则”中所述

当客户端连接时,它会向服务器发送它要使用的字符集的名称。服务器使用的名称,设置 character_set_client, character_set_resultscharacter_set_connection 系统变量。实际上,服务器SET NAMES使用字符集名称执行 操作。

这样做的效果是你无法控制的客户端字符由开始设定的mysqld用 --character-set-server=utf8但是,一些亚洲客户更喜欢MySQL 4.0的行为。为了能够保留这种行为,我们添加了一个 mysqld开关, --character-set-client-handshake可以关闭它 --skip-character-set-client-handshake如果启动mysqld的使用 --skip-character-set-client-handshake,那么,当客户端连接时,它发送的字符集的名称,它希望使用的服务器。但是,服务器会忽略来自客户端的此请求

举例来说,假设您最喜欢的服务器字符集是latin1(不太可能在CJK区域,但这是默认值)。进一步假设客户端使用, utf8因为这是客户端操作系统支持的内容。现在,使用latin1默认字符集启动服务器 

mysqld --character-set-server=latin1

然后使用默认字符集启动客户端 utf8

mysql --default-character-set=utf8

通过查看以下输出可以看到生成的设置 SHOW VARIABLES

mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------------------+
| Variable_name            | Value                                  |
+--------------------------+----------------------------------------+
| character_set_client     | utf8                                   |
| character_set_connection | utf8                                   |
| character_set_database   | latin1                                 |
| character_set_filesystem | binary                                 |
| character_set_results    | utf8                                   |
| character_set_server     | latin1                                 |
| character_set_system     | utf8                                   |
| character_sets_dir       | /usr/local/mysql/share/mysql/charsets/ |
+--------------------------+----------------------------------------+

现在停止客户端,并使用mysqladmin停止服务器 然后再次启动服务器,但这次告诉它跳过这样的握手:

mysqld --character-set-server=utf8 --skip-character-set-client-handshake

utf8再次 启动客户端作为默认字符集,然后显示结果设置:

mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------------------+
| Variable_name            | Value                                  |
+--------------------------+----------------------------------------+
| character_set_client     | latin1                                 |
| character_set_connection | latin1                                 |
| character_set_database   | latin1                                 |
| character_set_filesystem | binary                                 |
| character_set_results    | latin1                                 |
| character_set_server     | latin1                                 |
| character_set_system     | utf8                                   |
| character_sets_dir       | /usr/local/mysql/share/mysql/charsets/ |
+--------------------------+----------------------------------------+

通过比较不同的结果可以看出, SHOW VARIABLES如果使用该--skip-character-set-client-handshake 选项,服务器将忽略客户端的初始设置 

 参考: https://dev.mysql.com/doc/refman/8.0/en/faqs-cjk.html 

            A.11 MySQL 8.0 FAQ:MySQL中文,日文和韩文字符集

原文地址:https://www.cnblogs.com/DataArt/p/10089721.html