MySQL 亂碼本質是「編碼/解碼不一致」。本文用流程圖解析存入/讀出三次編碼轉換,深度剖析錯進錯出失效條件,提供 Dump&Reload 與 Binary 中轉兩大標準修復方案。
character_set_client (C2) 解碼character_set_client (C2') 編碼 → 二進制流-- 客戶端 UTF-8,Server 設 GBK,表 UTF-8
SET NAMES gbk;
INSERT INTO utf8_table (col) VALUES ('中文');
-- Warning: Incorrect string value: '\xE4\xB8\xAD\xE6\x96\x87'
-- 結果存入亂碼,讀出永久損壞
GBK 無法表示部分 UTF-8 字符,轉換時替換為 0x3F (?),資料永久遺失。
CREATE TABLE t (c VARCHAR(50)) CHARSET=latin1;
SET NAMES latin1;
INSERT INTO t VALUES ('中文'); -- 實際寫入 UTF-8 位元組
SELECT c FROM t; -- 終端 UTF-8 顯示正常
latin1 1:1 映射 0x00-0xFF,不處理超出範圍字符,保留原始位元組,形成「錯進錯出」假象。
# 客戶端/連線/表 統一字元集 [client] default-character-set = utf8mb4 [mysqld] character-set-server = utf8mb4 # 建表指定 CREATE TABLE t (...) CHARSET=utf8mb4;
mysqldump -u root -p --default-character-set=utf8 --skip-set-charset db table > data.sqlCREATE TABLE new_t (...) CHARSET=utf8mb4;mysql -u root -p --default-character-set=utf8mb4 db < data.sql-- 步驟1: 字串欄位 → VARBINARY (不轉碼,保留原始位元組) ALTER TABLE t MODIFY COLUMN c VARBINARY(50); -- 步驟2: VARBINARY → 目標字元集 (按新字元集重新解碼) ALTER TABLE t MODIFY COLUMN c VARCHAR(50) CHARACTER SET utf8mb4;
原理:MySQL 字串→二進制不轉碼,二進制→字串按目標字元集編碼,等同於在 Server 端完成「錯出→正入」。
| 錯誤方案 | 後果 |
|---|---|
| ALTER TABLE ... CHARSET=xxx | 僅修改表預設字元集,現有欄位/資料不變 |
| ALTER TABLE ... CONVERT TO CHARSET=xxx | 對「錯進錯出」資料會二次轉碼徹底損壞 |