mysql 修改字符集爲utf8mb4

通常狀況下,咱們會設置MySQL默認的字符編碼爲utf8,可是近些年來,emoji表情的火爆使用,給數據庫帶來了意外的錯誤,就是emoji的字符集已經超出了utf8的編碼範疇😄mysql

使人抓狂的字符編碼問題

談到字符編碼問題,會讓不少人感到頭疼,這裏不在深究各個字符編碼的特色和理論,這裏只說下Unicode和utf8字符編碼的關係sql

1
2
3
4
5
6
7
Unicode是編碼字符集,而UTF-8就是字符編碼,即Unicode規則字庫的一種實現形式。
隨着互聯網的發展,對同一字庫集的要求愈來愈迫切,Unicode標準也就天然而然的出現。
它幾乎涵蓋了各個國家語言可能出現的符號和文字,並將爲他們編號。
詳見:Unicode on Wikipedia。
Unicode的編號從0000開始一直到10FFFF共分爲16個Plane,每一個Plane中有65536個字符。
而UTF-8則只實現了第一個Plane,可見UTF-8雖然是一個當今接受度最廣的字符集編碼,
可是它並無涵蓋整個Unicode的字庫,這也形成了它在某些場景下對於特殊字符的處理困難

簡單的說在計算機內存中,統一使用Unicode編碼,當須要保存到硬盤或者須要傳輸的時候,就轉換爲UTF-8編碼數據庫

用記事本編輯的時候,從文件讀取的UTF-8字符被轉換爲Unicode字符到內存裏,編輯完成後,保存的時候再把Unicode轉換爲UTF-8保存到文件vim

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. 備份

安全第一,備份全部須要升級字符編碼的數據庫spa

  • 能夠將庫dump出來
  • 若是是虛擬機,能夠給整個主機作快照

2. 升級

utf8mb4是MySQL5.5.3版本以後支持的字符集,so,若是你須要使用這個字符集,前提條件是你的MySQL版本必須 >= 5.5.33d

3. 修改

在MySQL中,能夠爲一個database設置字符編碼,能夠爲一張表設置字符編碼,甚至能夠爲某一個字段設置字符編碼rest

  • 查看當前系統默認的字符集設置

    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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> vim /etc/my.cnf
# 對本地的mysql客戶端的配置
[client]
default-character-set = utf8mb4

# 對其餘遠程鏈接的mysql客戶端的配置
[mysql]
default-character-set = utf8mb4

# 本地mysql服務的配置
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
> service mysqld restart

檢查修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name | Value |
+--------------------------+--------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+--------------------------+--------------------+
10 rows in set (0.00 sec)

注: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. 🍻

相關文章
相關標籤/搜索