MySQL 4.1+ 引入四層字符集體系:server → database → table → connection。預設編譯/安裝/啟動參數皆為 latin1(ISO-8859-1),導致:
mysqldump 導出時未指定 --default-character-set,進一步加劇碼點錯位。SET NAMES 'gbk'; -- 相當於
SET character_set_client = gbk;
SET character_set_connection = gbk;
SET character_set_results = gbk;
應用連線建立後第一條 SQL必須執行此語句,確保「連線層」編碼與應用一致。
[mysqld]
default-character-set = utf8 # 5.5+ 建議 utf8mb4
collation-server = utf8_general_ci
[mysql] # 客戶端工具 (mysql, mysqladmin, mysqldump 等)
default-character-set = utf8
重啟服務生效。注意:[client] 區段同樣影響連線層,建議同步設定。
# 1. 以 latin1 讀取,輸出為 gbk(或 utf8)
mysqldump -uroot -p --default-character-set=latin1 \
--set-charset=gbk --skip-opt db_name > db_gbk.sql
# 2. 建立目標字符集資料庫
mysql -uroot -p -e "CREATE DATABASE db_name DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;"
# 3. 以 gbk 導入
mysql -uroot -p --default-character-set=gbk -f db_name < db_gbk.sql
參數解析:--default-character-set=latin1 告訴 dump「源資料按 latin1 讀」;--set-charset=gbk 在輸出檔寫入 SET NAMES gbk;--skip-opt 關閉預設優化(避免 SET NAMES latin1 干擾)。
DEFAULT CHARSET=latin1 → DEFAULT CHARSET=gbk(或刪除該子句,依賴庫級預設)。CHARACTER SET latin1 → CHARACTER SET gbk。cdb_sessions (HEAP) 建議刪除該段,重新安裝後再導入。缺點:大檔案編輯器易崩潰、易漏替、不易自動化。
mysqldump 導出 → 建立正確字符集庫 → 導入。mysqldump -uroot -p --default-character-set=latin1 \
--set-charset=gbk --skip-opt --compatible=mysql40 db_name > db_40.sql
--compatible=mysql40 生成 4.0 相容 SQL(無 ENGINE=、無 CREATE TABLE ... SELECT 等)。
| 現象 | 根因 | 修正 |
|---|---|---|
| 問號 ??? / 亂碼 | 連線層編碼不匹配 | 連線後首句 SET NAMES ...;JDBC URL 加 characterEncoding=utf8 |
| 中文變兩個問號 | utf8mb4 字符寫入 utf8 表 | 表改 CHARSET=utf8mb4 或應用過濾補充平面字符 |
| 導入報錯 Unknown collation | 目標版本不支援該排序規則 | 導出加 --skip-set-charset,導入前手動建庫指定支援的 collation |
| 資料量暴增 30% | latin1 → utf8 多字節存儲 | 預期現象,規劃磁碟空間 |
pt-table-checksum (Percona Toolkit) 比對源/目標資料一致性。gh-ost / pt-online-schema-change 避免鎖表。SELECT HEX(col), CHARSET(col) FROM t LIMIT 10 直觀查看碼點。字符集遷移核心三步:統一連線層 → 正確導出轉碼 → 目標庫正確字符集導入。版本跨度大時務必加 --compatible。生產環境嚴禁直接拷貝 data 目錄升級。建立「連線即 SET NAMES」開發規範,從源頭杜絕亂碼。