一般情況下,我們會設置MySQL默認的字符編碼為utf8,但是近些年來,emoji表情的火爆使用,給數據庫帶來了意外的錯誤,就是emoji的字符集已經超出了utf8的編碼范疇😄
令人抓狂的字符編碼問題
談到字符編碼問題,會讓很多人感到頭疼,這里不在深究各個字符編碼的特點和理論,這里只說下Unicode和utf8字符編碼的關系
1 |
Unicode是編碼字符集,而UTF-8就是字符編碼,即Unicode規則字庫的一種實現形式。 |
簡單的說在計算機內存中,統一使用Unicode編碼,當需要保存到硬盤或者需要傳輸的時候,就轉換為UTF-8編碼
用記事本編輯的時候,從文件讀取的UTF-8字符被轉換為Unicode字符到內存里,編輯完成后,保存的時候再把Unicode轉換為UTF-8保存到文件

emoji是Unicode編碼,在MySQL中使用utf8編碼無法正常顯示emoji的表情,為了解決這個問題,MySQL在5.5.3版本之后,引進了新的字符編碼utf8mb4,本篇文章主要介紹如何將已經是utf8的database切換到utf8mb4字符編碼
什么是utf8mb4
utf8mb4最明顯的好處是解決了蘋果挖的坑-推廣了emoji表情。utf8mb4解決了MySQL數據庫存儲emoji表情的問題
utf8mb4是utf8的超集,理論上由utf8升級到utf8mb4字符編碼沒有任何兼容問題
升級utf8到utf8mb4
1. 備份
安全第一,備份所有需要升級字符編碼的數據庫
- 可以將庫dump出來
- 如果是虛擬機,可以給整個主機做快照
2. 升級
utf8mb4是MySQL5.5.3版本之后支持的字符集,so,如果你需要使用這個字符集,前提條件是你的MySQL版本必須 >= 5.5.3
3. 修改
在MySQL中,可以為一個database設置字符編碼,可以為一張表設置字符編碼,甚至可以為某一個字段設置字符編碼
- 查看當前系統默認的字符集設置
SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
- 查看database的字符編碼
show create database polarsnow;
- 查看table的字符編碼
show create table ps;
- 查看column的字符編碼
show full columns from ps;
修改database默認的字符集
ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci
雖然修改了database的字符集為utf8mb4,但是實際只是修改了database新創建的表,默認使用utf8mb4,原來已經存在的表,字符集並沒有跟着改變,需要手動為每張表設置字符集
修改table的字符集
- 只修改表默認的字符集
ALTER TABLE table_name DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 修改表默認的字符集和所有字符列的字符集
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
單獨修改column默認的字符集
ALTER TABLE table_name CHANGE column_name column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
注:VARCHAR(191) 根據字段實例的類型填寫
4. 檢查字段的最大長度和索引列
- 字段長度
由於從utf8升級到了utf8mb4,一個字符所占用的空間也由3個字節增長到4個字節,但是我們當初創建表時,設置的字段類型以及最大的長度沒有改變。例如,你在utf8下設置某一字段的類型為TINYTEXT, 這中字段類型最大可以容納255字節,三個字節一個字符的情況下可以容納85個字符,四個字節一個字符的情況下只能容納63個字符,如果原表中的這個字段的值有一個或多個超過了63個字符,那么轉換成utf8mb4字符編碼時將轉換失敗,你必須先將TINYTEXT更改為TEXT等更高容量的類型之后才能繼續轉換字符編碼
- 索引
在InnoDB引擎中,最大的索引長度為767字節,三個字節一個字符的情況下,索引列的字符長度最大可以達到255,四個字節一個字符的情況下,索引的字符長度最大只能到191。如果你已經存在的表中的索引列的類型為VARCHAR(255)那么轉換utf8mb4時同樣會轉換失敗。你需要先將VARCHAR(255)更改為VARCHAR(191)才能繼續轉換字符編碼
5. 修改配置文件
SET NAMES utf8 COLLATE utf8_unicode_ci becomes SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci
1 |
> vim /etc/my.cnf |
檢查修改
1 |
mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%'; |
注:character_set_system 一直都會是 utf8,不能被更改
6. 修復&優化所有數據表
1 |
> mysqlcheck -u root -p --auto-repair --optimize --all-databases |
總結
不要在MySQL上使用utf8字符編碼,推薦使用utf8mb4,至於為什么,引用國外友人的一段話:
Never use utf8 in MySQL — always use utf8mb4 instead. Updating your databases and code might take some time, but it’s definitely worth the effort. Why would you arbitrarily limit the set of symbols that can be used in your database? Why would you lose data every time a user enters an astral symbol as part of a comment or message or whatever it is you store in your database? There’s no reason not to strive for full Unicode support everywhere. Do the right thing, and use utf8mb4. 🍻
