在 MySQL 中,差不多有八种与字符集相关的系统参数,分别为:
- character_set_system
- character_set_server
- character_set_client
- character_set_database
- character_set_connection
- character_set_results
- character_set_filesystem
- character_sets_dir
上面的每一个系统参数都维护着 MySQL 中不同部分所使用的字符集。可以通过 show variables like '%char%'; 来查看这几个系统参数的值。
character_set_system
文档里对 character_set_system 的描述是:
The character set used by the server for storing identifiers.
所谓 identifiers ,其实就是数据库的 metadata,所谓 metadata 其实就是那些用来描述数据库的信息但并不是数据库所存储的内容的数据,比如说 table 的列名,登录 MySQL 所使用的用户名,又或者是 MySQL 的版本信息等,这些都是 metadata。
也就是说, character_set_system 的值就是数据库的 metadata 所使用的字符集,在 MySQL 中,character_set_system 的值只能为 utf8,不能够进行修改。
character_set_server
文档里对 character_set_server 的描述是:
The servers default character set.
单单这一句描述并没有描述地很清楚。简单来说,当在没有指定 charset 的情况下使用 CREATE DATABASE 来创建数据库的时候,这个所创建的数据库就会默认使用 character_set_server 所指定的字符集。
可以通过以下的方式修改 character_set_server 的值:
- 启动 mysqld 的时候使用 --character-set-server 选项
- 在 my.ini 或者 my.cnf 中在 [mysqld] 中使用 character-set-server
- 使用 SET 语句
character_set_client
文档里对 character_set_client 的描述是:
The character set for statements that arrive from the client.
也就是说,在 MySQL 客户端(即 mysql 命令行,或者 Navicat 等)中执行某个语句(如 INSERT、DELETE、UPDATE 以及 SELECT 等)的话,这个语句将会使用 character_set_client 中所指定的字符集进行编码然后发送给 MySQL server 。
还有当下面介绍到的 character_set_filesystem 的值为 binary 的时候,也会以 character_set_client 中所指定的字符集来编码 string literals 。
可以通过以下的方式修改 character_set_client 的值:
- 启动 mysql 的时候使用 --default-character-set 选项
- 在 my.ini 或者 my.cnf 中在 [client] 或者 [mysql] 中使用 default-character-set
- 使用 SET 语句
character_set_database
文档里对 character_set_database 的描述是:
The character set used by the default database.
即当前所在数据库所使用的字符集,所谓当前所在数据库,即 select database() 的结果。
其实我觉得这个系统参数除了能查看当前数据库做使用的字符集之外,并没有什么实质上的作用。
可能有人会觉得这个参数所指定的字符集就是在没有指定 charset 的情况下使用 CREATE DATABASE 来创建数据库的时候所使用的字符集,实际上并不是,这时候数据库使用的是 character_set_server 所指定的字符集。
根据官方文档的介绍,character_set_database 目前已经被弃用了,未来可能会被移除。
可以通过以下的方式修改 character_set_database 的值:
- 使用 SET 语句
character_set_connection
文档里对 character_set_connection 的描述是:
The character set used for literals specified without a character set introducer and for number-to-string conversion.
所谓的 literals 其实就是双引号或者单引号里的字符串,比如说 select _utf8 ' 这里是 nicechiblog.com '; ,这里 ”这里是 nicechiblog.com“ 就是 literals ,而_utf8 就是这个 literals 的 introducer ,也就是说这个 literals 用 utf8 字符集进行编码,如果没有对这个 literals 使用指定的 introducer 的话,就会使用 character_set_connection 所指定的字符集进行编码。
其实 MySQL server 在处理 client 所发送来的语句之后,将会把这些发送来的语句转换成 character_set_connection 所指定的字符集,而 client 发送来的语句的字符集本身使用的是 character_set_client 所指定的字符集。
可以通过以下的方式修改 character_set_connection 的值:
- 使用 SET 语句
character_set_results
文档里对 character_set_results 的描述是:
The character set used for returning query results to the client.
简单来说,server 返回给 client 的结果使用的就是 character_set_results 所指定的字符集,比如说 SELECT * FROM XXX; 所返回的结果所使用的字符集就是 character_set_results 所指定的字符集。
可以通过以下的方式修改 character_set_results 的值:
- 使用 SET 语句
character_set_filesystem
文档里对 character_set_filesystem 的描述是:
The file system character set.
简单来说,就是 MySQL 如果要读取本地系统的文件的时候,解析文件名就是采用 character_set_filesystem 所指定的字符集。
假设使用 LOAD DATA 命令来加载本地的文件:
#将 E 盘的文件 哈哈哈.txt 中的内容导入到 test 数据库的 test1 表中
LOAD DATA LOCAL INFILE 'E:\哈哈哈.txt' INTO TABLE test.test1
此时,解析 ”哈哈哈.txt“ 文件名所使用的字符集就是 character_set_filesystem 所指定的字符集。如果解析文件名的时候所使用的字符集不正确,则解析之后的文件名就很有可能是乱码,LOAD DATA 命令就会读取文件失败。详情请移步 mysql LOAD DATA File xxx not found (Errcode: 22 "Invalid argument") 加载中文名文件失败的解决方法 。
默认的 character_set_filesystem 值为 binary ,即意味着将会使用 character_set_client 所指定的字符集对文件名进行解析。
可以通过以下的方式修改 character_set_filesystem 的值:
- 启动 mysqld 的时候使用 --character-set-filesystem 选项
- 在 my.ini 或者 my.cnf 中在 [mysqld] 中使用 character-set-filesystem
- 使用 SET 语句
character_sets_dir
文档里对 character_sets_dir 的描述是:
The directory where character sets are installed.
即安装字符集的目录。
可以通过以下的方式修改 character_sets_dir 的值:
- 启动 mysqld 或者 mysql 的时候使用 --character-sets-dir 选项
- 在 my.ini 或者 my.cnf 中在 [mysqld] / [client] / [mysql] 中使用 character-sets-dir