Mysql Collation 校验对于索引的影响
文章目录
起因
最近线上出现了一个奇怪的问题:用户昵称字段使用了唯一索引,但是在 sentry 中经常收到昵称冲突的错误。 这种异常错误引起了我的兴趣,决定探一个究竟。
探究
我们在使用 mysql 过程中,一般创建表会使用如下:
|
|
我们没有显示声明使用的字符集和校验类型,那么这个表就是使用默认值。我们看一下默认值是什么:
mysql> select * from information_schema.SCHEMATA where SCHEMA_NAME='test';
+--------------+-------------+----------------------------+------------------------+----------+
| CATALOG_NAME | SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME | SQL_PATH |
+--------------+-------------+----------------------------+------------------------+----------+
| def | test | utf8mb4 | utf8mb4_general_ci | NULL |
+--------------+-------------+----------------------------+------------------------+----------+
1 row in set (0.22 sec)
那么字符集为: utf8mb4, 字符校验为: utf8mb4_general_ci。
往表中分别插入 Abcd 和 abcd
|
|
通常意义上来讲,Abcd 和 abcd 肯定不是同一个字符串,但是对于添加了 unique 索引,字符集为 utf8mb4,字符校验为 utf8mb4_general_ci 的表来说,他们是一样的!!!WTF!
再试一下:
|
|
WTF!!!,完全和预期不一样了啊。到底咋回事呢?
解释
字符集: utf8mb4
字符集简单说就是数据库用什么编码来存储你的数据,就像我们写代码一般都是用 UTF8存取一样,为了兼容各种字符我们一般会选取utf8格式(注意 mysql 中的 utf8 并不是真正的 utf8, utf8mb4才是)。
字符校验: utf8mb4_general_ci。
可以理解为进行特殊比较用的,
Suffix | Meaning |
---|---|
_ai | Accent insensitive |
_as | Accent sensitive |
_ci | Case insensitive |
_cs | case-sensitive |
_ks | Kana sensitive |
_bin | Binary |
按照上表的话,我们默认的字符校验规则就是忽略大小写的。所以出现奇怪问题也不能怪 mysql, 只能说我们知识不足啊。
参考:
文章作者 霸气千秋
上次更新 2018-07-27