中文亂碼是 MySQL 開發中最高頻的坑,本質是**客戶端、連線、伺服器、資料庫、資料表、欄位**六層字符集不一致。本文從原理到配置,給出徹底解決方案與避坑清單。
utf8mb4_unicode_ci、utf8mb4_general_ci、gbk_chinese_ci)。
SHOW VARIABLES LIKE 'character_set_%';
SHOW VARIABLES LIKE 'collation_%';
-- 關鍵變數:
-- character_set_server 伺服器預設
-- character_set_database 當前庫預設
-- character_set_client 客戶端發送編碼
-- character_set_connection 連線層轉碼目標
-- character_set_results 結果集返回編碼
# /etc/my.cnf 或 /etc/mysql/my.cnf
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4' # 連線自動執行,不影響 root
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
重啟後驗證:SHOW VARIABLES LIKE 'character_set_%'; 全為 utf8mb4。
-- 連線後立即執行
SET NAMES utf8mb4;
-- 等價於
SET character_set_client = utf8mb4;
SET character_set_connection = utf8mb4;
SET character_set_results = utf8mb4;
| 框架/語言 | 配置方式 |
|---|---|
| PHP (PDO) | DSN: mysql:host=...;dbname=...;charset=utf8mb4 |
| PHP (mysqli) | $mysqli->set_charset('utf8mb4') |
| Python (PyMySQL) | charset='utf8mb4' 參數 |
| Java (JDBC) | URL: ?characterEncoding=utf8mb4&useUnicode=true |
| Go (go-sql-driver/mysql) | DSN: charset=utf8mb4,utf8 |
| Node.js (mysql2) | charset: 'utf8mb4' 選項 |
-- 資料庫級(僅影響後續新建表)
ALTER DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 資料表級(僅影響後續新增欄位)
ALTER TABLE tbl_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- **完整轉換現有資料**(含資料重寫,大表慎用,建議 pt-online-schema-change)
ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 單欄位修改
ALTER TABLE tbl_name MODIFY col_name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
| 現象 | 原因 | 解決 |
|---|---|---|
| 插入中文變「???」 | 字符集不支援(如 latin1) | 改 utf8mb4 |
| 讀出變「」或亂碼 | 寫入編碼 ≠ 讀取編碼 | 統一 SET NAMES / 配置檔 |
| Emoji 存入報錯 / 變?? | 用 utf8(僅 3 字節)而非 utf8mb4 | 全鏈路 utf8mb4 |
| 導出 SQL 導入後亂碼 | 導出/導入未指定字符集 | mysqldump --default-character-set=utf8mb4 / mysql --default-character-set=utf8mb4 |
| JDBC 連線亂碼 | URL 缺 characterEncoding | 加 ?characterEncoding=utf8mb4&useUnicode=true |
pt-online-schema-change 零停機轉換。SET NAMES utf8mb4,防止連線複用時字符集漂移。--default-character-set=utf8mb4。