Mysql字符集

引言

今天遇到一个问题,我们在设计一个User表时,用户名需要保证唯一,且不区分大小写。开始设计是两个字段user_name(原始值),user_name_upcase(转大写值),这两个字段上都唯一索引。直到有位同学告诉我们可通过一个字段搞定,学习了,学习了。

字符集&校对规则

MySQL提供了字符集(character set)支持,可以使用各种字符集存储数据并根据各种校对规则(collations)进行比较。可以在server, database, table, column 指定字符集和校对规则。

什么是字符集?

简单来说,字符集就是符号和编码的集合。举个例子,假设我们有四个字母A,B,a,b。我们给每一个字符一个数值:A=0,B=1,a=2,b=3。A就是符号,数值0就是A的编码,字符和数字的编码规则的合集就是字符集。

什么是校对规则?

简单来说,是字符之间的比较规则,决定字符相等和排序等。接着上面的例子,比较符号A,B的大小,我们可以简单的认为A < B,因为0 < 1,我们称这种规则为binary collation。但是,当我们需要认为A=a,B=b 即忽略大小写时,我们成为case-insensitive collation。

读懂字符集

查看当前数据库支持哪些字符集(数据库版本8.0)

mysql> SHOW CHARACTER SET;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
| binary   | Binary pseudo charset           | binary              |      1 |
...
| latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |
...
| ucs2     | UCS-2 Unicode                   | ucs2_general_ci     |      2 |
...
| utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_0900_ai_ci  |      4 |
...

utf8 这个是mysql历史遗留的一个utf8编码字符集,最大长度是3个字节,而真正的utf8编码是最长4个字节。

utf8mb4 真正的utf8编码字符集,可以完美支持所有的utf8编码,推荐使用。

查看utf8mb4支持哪些校对规则

mysql> SHOW COLLATION WHERE Charset = 'utf8mb4';
+----------------------------+---------+-----+---------+----------+---------+---------------+
| Collation                  | Charset | Id  | Default | Compiled | Sortlen | Pad_attribute |
+----------------------------+---------+-----+---------+----------+---------+---------------+
| utf8mb4_0900_ai_ci         | utf8mb4 | 255 | Yes     | Yes      |       0 | NO PAD        |
| utf8mb4_bin                | utf8mb4 |  46 |         | Yes      |       1 | PAD SPACE     |
| utf8mb4_general_ci         | utf8mb4 |  45 |         | Yes      |       1 | PAD SPACE     |
....

校对规则名称后缀含义表

后缀 含义 说明
_ai Accent-insensitive 重音不敏感,多见于德语
_as Accent-sensitive 重音敏感
_ci Case-insensitive 大小写不敏感
_cs Case-sensitive 大小写敏感
_ks Kana-sensitive
_bin Binary 二进制比较

使用字符集

例如,我们创建如下表


CREATE TABLE `test_charset` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `text_bin` VARCHAR(45) COLLATE UTF8MB4_BIN NOT NULL,
    `text_ci` VARCHAR(45) COLLATE UTF8MB4_GENERAL_CI DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_text_ci` (`text_ci`)
)  ENGINE=INNODB AUTO_INCREMENT=10 DEFAULT CHARSET=UTF8MB4 COLLATE = UTF8MB4_BIN;

实际上,可以在服务器,数据库,表,字段上使用不同的字符集和校对规则,针对我们这种忽略大小写的需求,可以单独指定该列的校对规则为UTF8MB4_GENERAL_CI。

但是,没有特殊情况,建议还是一个数据库统一用一套配置,多了你自己不心慌吗?

UTF8MB4_GENERAL_CI 实现的源码分析

很好奇mysql里面到底是怎么处理忽略大小写这件事情的,这个就得看下mysql源码了,mysql源码地址:https://github.com/mysql/mysql-server,直接到最后ctype-utf8.cc这个源码文件。

Mysql字符集_第1张图片
1.png
Mysql字符集_第2张图片
2.png

通过mysql的源码,我们可以看到mysql服务内部会都转成小写进行比较。

总结

mysql包含的东西太多,多学习吧。

参考文档

https://github.com/mysql/mysql-server/blob/8.0/strings/ctype-utf8.cc
https://dev.mysql.com/doc/refman/8.0/en/charset.html
https://dev.mysql.com/doc/refman/8.0/en/charset-collation-names.html
https://dev.mysql.com/doc/refman/8.0/en/charset-mysql.html

你可能感兴趣的:(Mysql字符集)