为了支持各个国家的不同语言,MySQL 从4.0 版本开始支持了很多种字符集,且每种字符集支持了 N 多种排序规则。我们可以在建表的时候指定字符集的排序规则,不指定时会有一个默认规则。

字符集和排序规则总是一起使用的,每个排序规则都是针对某个特性的字符集,和其他字符集没有关系。

只有基于 字符串 的值才有 字符集 的概念。其他类型的值,像 int,float,bool 字符集的配置只是一种声明。

每个 database 有自己的字符集和排序规则默认值,每张表可以指定自己的字符集和排序规则,同一张表的不同字段也可以指定自己的字符集和排序规则。这是一个逐层继承的默认设置。

查看 MySQL 支持的字符集

  1. show charset 命令可以查看当前版本支持哪些字符集
  2. mysql> show charset;
  3. +----------+---------------------------------+---------------------+--------+
  4. | Charset | Description | Default collation | Maxlen |
  5. +----------+---------------------------------+---------------------+--------+
  6. | armscii8 | ARMSCII-8 Armenian | armscii8_general_ci | 1 |
  7. | ascii | US ASCII | ascii_general_ci | 1 |
  8. | big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
  9. | binary | Binary pseudo charset | binary | 1 |
  10. Charset:支持的字符集
  11. Default collation:默认排序规则。常用的规则( _ci 结尾表示大小写不敏感;_cs 结尾表示大小写敏感;_bin 表示二进制的比较
  12. Maxlen:最大支持的字节数
  13. show collation 查看字符集支持的哪些排序规则
  14. mysql> show collation like 'gbk%';
  15. +----------------+---------+----+---------+----------+---------+---------------+
  16. | Collation | Charset | Id | Default | Compiled | Sortlen | Pad_attribute |
  17. +----------------+---------+----+---------+----------+---------+---------------+
  18. | gbk_bin | gbk | 87 | | Yes | 1 | PAD SPACE |
  19. | gbk_chinese_ci | gbk | 28 | Yes | Yes | 1 | PAD SPACE |
  20. +----------------+---------+----+---------+----------+---------+---------------+
  21. 2 rows in set (0.02 sec)

配置字符集和排序规则

在 my.cnf 文件中配置默认字符集

  1. > cat my.cnf
  2. [client] # 客户端连接时的字符集
  3. default-character-set = utf8mb4
  4. [mysql] # mysql shell 登录时的字符集
  5. default-character-set = utf8mb4
  6. [mysqld] # 服务端字符集
  7. character-set-server = utf8mb4
  8. collation-server = utf8mb4_general_ci # 排序规则

在 session 会话中配置字符集

  1. 执行 status 命令查看当前会话的字符集
  2. mysql> status
  3. --------------
  4. ...
  5. Server characterset: utf8mb4
  6. Db characterset: utf8mb4
  7. Client characterset: utf8mb4
  8. Conn. characterset: utf8mb4
  9. ...
  10. 修改 当前会话的字符集
  11. mysql> set NAMES "utf8";
  12. Query OK, 0 rows affected, 1 warning (0.03 sec)
  13. mysql> status
  14. --------------
  15. ...
  16. Server characterset: utf8mb4
  17. Db characterset: utf8mb4
  18. Client characterset: utf8mb3 # 只能修改会话参数,而没有修改服务端。
  19. Conn. characterset: utf8mb3
  20. ...

建表的时候配置字符集

  1. a 列指定了 gbk 字符集,排序规则默认
  2. b 列指定了 utf8 字符集,排序规则是 utf8mb4_general_ci
  3. c 列字符集和排序规则都是表 t4 的默认值 CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  4. 这是一个逐层继承的默认设置,但通常不需要这么配置。
  5. mysql> CREATE TABLE t4 (
  6. a VARCHAR(2) CHARSET GBK,
  7. b VARCHAR(4) CHARSET UTF8 COLLATE UTF8_GENERAL_CI,
  8. c VARCHAR(6)
  9. );
  10. mysql> show create table t4 \G;
  11. Create Table: CREATE TABLE t4 (
  12. a varchar(2) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT NULL,
  13. b varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  14. c varchar(6) DEFAULT NULL
  15. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

1. 隐式转换之字符集

只有字符集相同的字段才能做比较运算,如果字符集不同,MySQL 会先将其准换成同一个字符集再进行比较。(如果两个字符集不兼容的话则报错)

  1. 接上面的例子 t4
  2. mysql> show full columns from t4;
  3. +-------+------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
  4. | Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
  5. +-------+------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
  6. | a | varchar(2) | gbk_chinese_ci | YES | | NULL | | select,insert,update,references | |
  7. | b | varchar(4) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
  8. | c | varchar(6) | utf8_unicode_ci | YES | | NULL | | select,insert,update,references | |
  9. +-------+------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
  10. 插入一些测试数据:
  11. insert into t4 select "跑步","跑步","ff";
  12. insert into t4 select "aa","aa","cc";
  13. insert into t4 select "aa","bb","dd";
  14. mysql> select * from t4;
  15. +--------+--------+------+
  16. | a | b | c |
  17. +--------+--------+------+
  18. | 跑步 | 跑步 | ff |
  19. | aa | aa | cc |
  20. | aa | bb | dd |
  21. +--------+--------+------+
  22. a, b 字段比较测试:
  23. mysql> select t4.*, if(a=b,"a==b","a!=b") ret from t4 where c="ff";
  24. +--------+--------+------+------+
  25. | a | b | c | ret |
  26. +--------+--------+------+------+
  27. | 跑步 | 跑步 | ff | a==b |
  28. +--------+--------+------+------+
  29. a, b 列是不同的字符集。 gbk 存中文字符 占两个字节,utf8 是三个字节,存储方式不同,显然不能直接比较。但测试结果返回 True。这是因为优化器帮我们隐式类型转换了。
  30. 可以 trace 验证一下:( trace 分析器可以追踪到优化器具体是如何执行 sql,和选择执行计划的
  31. mysql> set optimizer_trace='enabled=on',end_markers_in_json=on; # 开启trace分析器会对 MySQL 性能有所影响,建议只在 优化分析问题时临时开启。
  32. mysql> select * from information_schema.optimizer_trace \G; # 查看分析结果
  33. *************************** 1. row ***************************
  34. QUERY: select t4.*, if(a=b,"a==b","a!=b") ret from t4 where c="ff"
  35. TRACE: {
  36. "steps": [
  37. {
  38. "join_preparation": {
  39. "select#": 1,
  40. "steps": [
  41. {
  42. "expanded_query": "/* select#1 */ select `t4`.`a` AS `a`,`t4`.`b` AS `b`,`t4`.`c` AS `c`,if((convert(`t4`.`a` using utf8) = `t4`.`b`),'a==b','a!=b') AS `ret` from `t4` where (`t4`.`c` = 'ff')"
  43. }
  44. ] /* steps */
  45. } /* join_preparation */
  46. },
  47. {
  48. "join_optimization": {
  49. "select#": 1,
  50. "steps": [
  51. {
  52. "condition_processing": {
  53. "condition": "WHERE",
  54. "original_condition": "(`t4`.`c` = 'ff')",
  55. ...
  56. 优化器用 convert() 函数,把 gbk 转成了 utf8,然后再对比:
  57. expanded_query": "/* select#1 */ select `t4`.`a` AS `a`,`t4`.`b` AS `b`,`t4`.`c` AS `c`,if((convert(`t4`.`a` using utf8) = `t4`.`b`)

2. 字符集使用时的一些其他问题

  1. join 关联查询时,被关联的列,如果是不同的字符集,那么关联的列会有索引失效的情况。
  2. 影响大小写字符的比较 utf8 默认的排序规则是 _ci 时 ,也就是大小写不敏感,那么查询的时候 select * from t where c1="a",会同时返回 c1="a" 和 c1="A"

    和预期的结果不一致。敏感还是不敏感要视业务需求而定。
  3. 在大小写不敏感的列上创建唯一索引时,可能会失败,因为可能会出现重复的列值,建索引时 Btree 需要先对列值比较排序。
  4. 不同的字符集校对规则之间的转换会带来额外的系统开销,性能会有下降。

MySQL 字符集相关的更多相关文章

  1. RDS For MySQL 字符集相关说明

    https://help.aliyun.com/knowledge_detail/41706.html?spm=5176.7841698.2.9.F5YjI5 字符序命名规则 字符集相关 MySQL  ...

  2. 从一个慢查询到MySQL字符集编码

    从一个慢查询到MySQL字符集编码 目录 从一个慢查询到MySQL字符集编码 1. 问题起源 2. MySQL字符集和字符集排序规则 2.1 字符集相关概念 2.2 MySQL中的字符集和字符集排序规 ...

  3. MySQL字符集编码相关

    Windows 10家庭中文版,MySQL  5.7.20,2018-05-07 Part.1 查找数据库的字符集编码 查看MySQL字符集编码:status命令 使用命令行登录MySQL服务器,然后 ...

  4. Mysql字符集设置

    转 基本概念 • 字符(Character)是指人类语言中最小的表义符号.例如’A'.’B'等:• 给定一系列字符,对每个字符赋予一个数值,用数值来代表对应的字符,这一数值就是字符的编码(Encodi ...

  5. MySQL字符集

    字符集的选择 1.如果数据库只需要支持中文,数据量很大,性能要求也很高,应该选择双字节定长编码的中文字符集(如GBK).因为相对于UTF-8而言,GBK"较小",每个汉字只占2个字 ...

  6. Mysql字符集知识总结

    字符集&字符编码方式 字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,这里的字符可以是英文字符,汉字字符,或者其他国家语言字符. 常见字符集 ...

  7. MySQL字符集转换引发插入乱码问题

    根据http://www.cnblogs.com/cchust/p/4601536.html进行验证测试 问题背景 在mysql上面执行一条普通的insert语句,结果报错: Incorrect st ...

  8. [MySQL] 字符集的选择

    1. Mysql支持的字符集 MySQL服务器可以支持多种字符集,不同的字段都可以使用不同的字符集. 查看所有可用字符集: show character set; select * from info ...

  9. Mysql优化相关总结

    Mysql优化相关总结 2016-05-31 数据库集中营 优化顺序: 选择适当的引擎和表结构和数据类型 建立索引,优化sql. 增加缓存,redis.memcache. 主从.主主,读写分离. my ...

随机推荐

  1. js实现网页中英文翻译

    1,html 2,metrics.js 3,需要 http://www.microsoftTranslator.com/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKk ...

  2. 【CF632F】Magic Matrix(生成树 脑洞)

    题目链接 大意 给定一个\(N\times N\)的矩阵,问是否满足以下三个条件: \(A_{i,i}=0\) \(A_{i,j}=A_{j,i}\) 对于任意的\(i,j,k\),满足\(A_{i, ...

  3. Java中的多线程你只要看这一篇就够了(引用)

    引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个 ...

  4. 磁盘管理+三剑客之awk

    目录 磁盘管理+三剑客之awk 一.磁盘管理 二.格式化命令awk 1.awk的语法 2.参数 3.awk的生命周期 4.awk中的预定义变量 5.awk处理规则的执行流程 6.awk中的函数 7.a ...

  5. mysql 查询附近N公里内数据

    mysql 查询一个地点(经纬度) 附近N公里内的数据.(根据一个地点的经纬度查询这个地点方圆几公里内的数据)1.创建测试表 CREATE TABLE `location` ( `id` int(10 ...

  6. 在线pdf请你谨慎打开

    本篇其实算之前安全整改话题的一点补充,对之前内容感兴趣的可以走以下快捷通道: 安全漏洞整改系列(二) 安全漏洞整改系列(一) 背景 前不久某家客户对我们提供的系统又进行了一轮安全测试,其中有一条我觉得 ...

  7. Java NIO Selector 的使用

    之前的文章已经把 Java 中 NIO 的 Buffer.Channel 讲解完了,不太了解的可以先回过头去看看.这篇文章我们就来聊聊 Selector -- 选择器. 首先 Selector 是用来 ...

  8. [自动化]ansible-系统安全加固整改

    基线漏洞安全整改 修复环境:centos7及以上 安全基线的概念 安全基线是一个信息系统的最小安全保证,即该信息系统最基本需要满足的安全要求.信息 系统安全往往需要在安全付出成本与所能够承受的安全风险 ...

  9. operator的解释

    operator是C++的关键字,它和运算符一起使用,表示一个运算符函数,理解时应将operator=整体上视为一个函数名. 这是C++扩展运算符功能的方法,虽然样子古怪,但也可以理解:一方面要使运算 ...

  10. centos安装k8s集群

     准备工作 关闭swap,注释swap分区 swapoff -a 配置内核参数,将桥接的IPv4流量传递到iptables的链 cat > /etc/sysctl.d/k8s.conf < ...