如果你還因爲MySQL亂碼摸不着頭腦,如果你只知道存儲emoji表情時,需要使用utf8mb4
,但卻不知道爲什麼,那麼本篇文章或許能解開你的一些疑惑。
字符集和排序規則
什麼是字符集:
字符集
指的是某個字符範圍的編碼規則,一個字符映射成一個二進制數據的過程也叫做編碼
,將一個二進制數據映射到一個字符的過程叫做解碼
。
什麼是比較規則:
比較規則
是針對某個字符集中的字符比較大小的一種規則。在我們確定了字符集表示字符的範圍以及編碼規則後,怎麼比較兩個字符的大小呢?最容易想到的就是直接比較這兩個字符對應的二進制編碼的大小,比方說字符'a'
的編碼爲0x01
,字符'b'
的編碼爲0x02
,所以'a'
小於'b'
,這種簡單的比較規則也可以被稱爲二進制比較規則。當然比較規則有很多種,這裏我們只要理解什麼是比較規則就行了。
一些重要的字符集:
字符集有很多種,來看一下有哪些常見的:
-
ASCII
字符集共收錄128個字符,包括空格、標點符號、數字、大小寫字母和一些不可見字符。由於總共才128個字符,所以可以使用1個字節來進行編碼,我們看一些字符的編碼方式:
'L' -> 01001100(十六進制:0x4C,十進制:76) 'M' -> 01001101(十六進制:0x4D,十進制:77)
-
ISO 8859-1
字符集共收錄256個字符,是在
ASCII
字符集的基礎上又擴充了128個西歐常用字符(包括德法兩國的字母),也可以使用1個字節來進行編碼。這個字符集也有一個別名latin1
。 -
GB2312
字符集收錄了漢字以及拉丁字母、希臘字母、日文平假名及片假名字母、俄語西裏爾字母。其中收錄漢字6763個,其他文字符號682個。同時這種字符集又兼容
ASCII
字符集。 -
GBK
字符集GBK
字符集只是在收錄字符範圍上對GB2312
字符集作了擴充,編碼方式上兼容GB2312
。 -
utf8
字符集收錄地球上能想到的所有字符,而且還在不斷擴充。這種字符集兼容
ASCII
字符集,採用變長編碼方式,編碼一個字符需要使用1~4個字節,比方說這樣:'L' -> 01001100(十六進制:0x4C) '啊' -> 111001011001010110001010(十六進制:0xE5958A)
對於同一個字符,不同字符集也可能有不同的編碼方式。比如對於漢字'我'
來說,ASCII
字符集中根本沒有收錄這個字符,utf8
和gb2312
字符集對漢字我
的編碼方式如下:
utf8編碼:111001101000100010010001 (3個字節,十六進制表示是:0xE68891)
gb2312編碼:1011000010101110 (2個字節,十六進制表示是:0xB0AE)
MySQL中支持的字符集和排序規則
MySQL中的utf8和utf8mb4
我們上邊說utf8
字符集表示一個字符需要使用1~4個字節,但是我們常用的一些字符使用1~3個字節就可以表示了。而在MySQL
中字符集表示一個字符所用最大字節長度在某些方面會影響系統的存儲和性能,所以MySQL
中定義了:
utf8mb3
:閹割過的utf8
字符集,只使用1~3個字節表示字符。utf8mb4
:正宗的utf8
字符集,使用1~4個字節表示字符。
有一點需要大家十分的注意,在MySQL
中utf8
是utf8mb3
的別名,所以之後在MySQL
中提到utf8
就意味着使用1~3個字節來表示一個字符,如果大家有使用4字節編碼一個字符的情況,比如存儲一些emoji表情啥的,那請使用utf8mb4
。
MySQL
中支持幾十種字符集,這裏列出來幾個,Maxlen
代表該種字符集表示一個字符最多需要幾個字節
字符集名稱 | Maxlen |
---|---|
ascii |
1 |
latin1 |
1 |
gb2312 |
2 |
gbk |
2 |
utf8 |
3 |
utf8mb4 |
4 |
比較規則
一種字符集往往對應着若干種比較規則,MySQL
支持的字符集就已經非常多了,所以支持的比較規則更多,我們先只查看一下utf8
字符集下的比較規則:
mysql> SHOW COLLATION LIKE 'utf8\_%';
+--------------------------+---------+-----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+--------------------------+---------+-----+---------+----------+---------+
| utf8_general_ci | utf8 | 33 | Yes | Yes | 1 |
| utf8_bin | utf8 | 83 | | Yes | 1 |
| utf8_unicode_ci | utf8 | 192 | | Yes | 8 |
| utf8_icelandic_ci | utf8 | 193 | | Yes | 8 |
| utf8_latvian_ci | utf8 | 194 | | Yes | 8 |
......
| utf8_german2_ci | utf8 | 212 | | Yes | 8 |
| utf8_croatian_ci | utf8 | 213 | | Yes | 8 |
| utf8_unicode_520_ci | utf8 | 214 | | Yes | 8 |
| utf8_vietnamese_ci | utf8 | 215 | | Yes | 8 |
| utf8_general_mysql500_ci | utf8 | 223 | | Yes | 1 |
+--------------------------+---------+-----+---------+----------+---------+
27 rows in set (0.00 sec)
這些比較規則的命名還挺有規律的,具體規律如下:
-
比較規則名稱以與其關聯的字符集的名稱開頭。如上圖的查詢結果的比較規則名稱都是以
utf8
開頭的。 -
後邊緊跟着該比較規則主要作用於哪種語言,比如
utf8_polish_ci
表示以波蘭語的規則比較,utf8_spanish_ci
是以西班牙語的規則比較,utf8_general_ci
是一種通用的比較規則。 -
名稱後綴意味着該比較規則是否區分語言中的重音、大小寫啥的,具體可以用的值如下:
後綴 英文釋義 描述 _ai
accent insensitive
不區分重音 _as
accent sensitive
區分重音 _ci
case insensitive
不區分大小寫 _cs
case sensitive
區分大小寫 _bin
binary
以二進制方式比較 比如
utf8_general_ci
這個比較規則是以ci
結尾的,說明不區分大小寫。
每種字符集對應若干種比較規則,每種字符集都有一種默認的比較規則,SHOW COLLATION
的返回結果中的Default
列的值爲YES
的就是該字符集的默認比較規則,比方說utf8
字符集默認的比較規則就是utf8_general_ci
。