中文亂碼是 MySQL 使用者最常遇到的坑,本質是「編碼不一致」:存儲編碼、連線編碼、應用編碼、終端編碼任一環節不匹配即會產生亂碼。本文系統梳理字符集架構、配置檔修改、連線建立時指定編碼、排查步驟與生產環境標準化清單。
| 層級 | 變數 | 作用 | 查看命令 |
|---|---|---|---|
| 服務器 | character_set_server | 建庫建表預設字符集 | SHOW VARIABLES LIKE 'character_set_server'; |
| 資料庫 | character_set_database | 庫級預設(建表時繼承) | SHOW CREATE DATABASE db; |
| 資料表 | character_set_table | 表級預設(建欄位時繼承) | SHOW CREATE TABLE t; |
| 欄位 | character_set_column | 實際存儲編碼 | SHOW FULL COLUMNS FROM t; |
| 連線 | character_set_client/connection/results | 客戶端發送/服務端處理/結果返回編碼 | SHOW VARIABLES LIKE 'character_set_%'; |
# /etc/mysql/mysql.conf.d/mysqld.cnf [mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_general_ci # 或 utf8mb4_unicode_ci init_connect = 'SET NAMES utf8mb4' # 連線建立時自動執行(超級用戶除外) [client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4
⚠️utf8是utf8mb3別名,**不支援 Emoji/生僻字**(僅 3 字節),**必須用utf8mb4**。
-- 1. 庫級轉換(僅影響後續建表) ALTER DATABASE mydb CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci; -- 2. 表級轉換(含所有字符欄位、索引重建,大表慎用 pt-osc) ALTER TABLE mytable CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 3. 僅修改表預設字符集(不轉換現有欄位) ALTER TABLE mytable DEFAULT CHARACTER SET utf8mb4;
| 語言/驅動 | 正確做法 |
|---|---|
| PHP PDO | new PDO("mysql:host=...;dbname=...;charset=utf8mb4", $user, $pass) DSN 含 charset |
| PHP mysqli | mysqli_set_charset($link, 'utf8mb4') 連線後立即執行 |
| Java JDBC | URL 參數 ?characterEncoding=utf8mb4&connectionCollation=utf8mb4_general_ci 或 SET NAMES utf8mb4 |
| Python PyMySQL | charset='utf8mb4' 參數 |
| Go sqlx | DSN charset=utf8mb4 或 SET NAMES utf8mb4 |
SHOW VARIABLES LIKE 'character_set_%'; 確認連線三變數均為 utf8mb4。SELECT HEX(col), col FROM t WHERE id=1; 查看實際存儲字節,對照 UTF-8 編碼表判斷是否正確。mysqldump --default-character-set=utf8mb4 導出是否正確。character_set_server=utf8mb4utf8mb4(含 COLLATE)charset=utf8mb4SET NAMES utf8mb4mysqldump/mysqlbinlog/pt-* 工具均加 --default-character-set=utf8mb4亂碼不可怕,可怕的是「以為好了其實沒好」。建立全鏈路 utf8mb4 標準,並納入部署檢查清單,從根源杜絕編碼地獄。