较真点说,“字符集”指多个字符的合集,“字符编码”指对字符集中的字符进行编码的方式(方便信息传输)。
字符集 与 字符编码 是 1:N 的关系。
如,UTF-8 是针对 Unicode字符集 的一种编码方式。
在实际使用场景中,往往用 “字符集(Character Set)是xx” 来表示使用了哪种具体的 字符编码方式。
如 “此处使用的字符集是 UTF-8” 这句话其实是说 “此处使用了 Unicode 字符集,编码方式为 UTF-8”。
MySQL中的字符编码
在使用MySQL时,有多个数据传输点需要进行字符编码转换。每个转换点都有相应的系统变量来指示采用哪种字符编码。
字符集(编码)相关系统环境变量
可通过以下语句查询相关变量值。MySQL Workbench 中也有查看系统变量的界面。
show variables like 'character%';
变量名
值(示例)
含义
character_set_client
utf8
当前客户端所采用的字符编码。
用于解析客户端发出的语句。
character_set_connection
utf8
当前连接层所采用的字符编码。
用于解析未指定字符编码的文本,以及将数字转换为字符串。
character_set_database
utf8
当前所选默认数据库的字符编码。
如果选择另一个database作为默认数据库,该变量值也会随着改变;
如果未选择默认数据库,则该变量值取自 character_set_server
character_set_filesystem
binary
用于 解释(interpret)文件名字符串。
LOAD_FILE() 这类方法就会用到。
文件名会从 character_set_client 转换为 character_set_filesystem。
默认值为 binary,这意味着无需转换。
character_set_results
utf8
当前采用的查询结果字符编码。
MySQL向客户端返回查询结果时,会将结果数据按此编码方式编码。
character_set_server
utf8
MySQL服务端的默认字符编码。
character_set_system
utf8
MySQL服务端用于存储 标识符(identifier) 的字符编码。
该变量值永远为 utf8
character_sets_dir
/opt/mysql/share/charsets/
字符集(字符编码)的安装路径
MySQL支持的字符集(字符编码)
可通过以下语句查询MySQL支持的字符集(字符编码):
show character set;
MySQL字符编码转换
字符集(字符编码)设置准则
设置字符集(字符编码)是为了在方便使用的情况下,尽可能减少字符编码方式转换。
Column(字段)的字符集:业务需要存什么字符类型,就选什么字符集。
MySQL采用类似继承的方式指定Table的默认字符集。
每个 database 和 table 都有自己的字符集。
如果未显式指定 column 的字符集,column 将采用所在 table 的字符集;
如果未显式指定 table 的字符集,table 将采用所在 database 的字符集;
如果未显式指定 databae 的字符集,database 将采用MySQL Server的字符集。
根据客户端的实际需要选择 character_set_client、character_set_connection、character_set_results
character_set_client 与 character_set_connection 保持一致。
实际上,各种MySQL客户端工具框架一般都会让这三个值保持一致:character_set_client、character_set_connection、character_set_results。如,MySQL自带的命令行客户端允许用户设置启动参数 “default_character_set”,上述三个变量都会使用该值。
因为国际化(支持各种字符)是很常见的需要,所以绝大多数系统都采用 UTF-8。
关于为了支持表情符等特殊字符(非BMP)而使用 utf8mb4:这也许是见仁见智的选择。有些人选择 utf8mb4,也有些人选择自己搞一套特殊的“编码”规则(在应用程序端有额外的编解码操作)。
MySQL字符校对规则(Collation)
字符校对规则是用于字符比较和排序的一套规则。MySQL中,每种字符编码都有对应的默认校对规则。可通过以下语句查看MySQL支持的Collation:
show collation;
utf8_general_ci 和 utf8_unicode_ci 是两个典型的 Collation。两者都是大小写不敏感的。虽然 utf8_general_ci 可以使性能更好一点点,但对于绝大多数应用而言,这并不是性能瓶颈,对整体性能而言其提升效果微不足道。所以对于语言字符范围非常广的业务场景,还是推荐用 utf8_unicode_ci 以获得更好的支持。
(utf8_bin 是大小写敏感的。)
另外,很多人推荐使用 utf8mb4。其对应的校对规则可选 utf8mb4_unicode_ci