MySQL 4.1 引入多字符集支持,默認 latin1 導致存入 GBK 數據的應用出現亂碼。本文深度剖析亂碼成因,提供從數據庫導出、文件轉碼、服務端/客戶端配置、PHP 代碼批量轉碼、HTML 聲明、編輯器設置的完整 UTF-8 遷移路徑。
應用(GBK) → 連接層(無聲明) → Server(latin1) → 存儲(latin1 偽裝 GBK 字節) 查詢時:Server(latin1) → 連接層(無轉換) → 應用(GBK) → 顯示正常 跨工具/備份/遷移時:字節流被誤判為 latin1 → 轉碼為 UTF-8 → 字節錯位 → 亂碼
# 導出 (指定 latin1 避免雙重轉換)
mysqldump -h 192.168.2.2 -u root -p --add-drop-table -c \
--set-charset=latin1 --allow-keywords --force dbname > 1.sql
# iconv 轉碼 (GBK → UTF-8)
iconv -c -f gb2312 -t utf-8 1.sql -o 2.sql
# -c 忽略無法轉換字符,-f 源編碼,-t 目標編碼
二進制列處理:若含 BLOB 未 Base64 編碼,需單獨導出、Base64 編碼後再轉碼,否則字節流破損。
# /etc/my.cnf
[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4' # 連接初始化
[mysql]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4
重啟 MySQL:service mysql restart
mysql -u root -p test < 2.sql
# 1. 從 CVS/SVN 導出乾淨代碼
cvs -d :pserver:user@host:/repo co project
# 2. 刪除無需轉換文件 (圖片、二進制、第三方庫)
# 3. 批量轉換 PHP/HTML/JS/CSS
find . -type f \( -name "*.php" -o -name "*.html" -o -name "*.js" -o -name "*.css" \) \
-exec sh -c 'iconv -f gb2312 -t utf-8 "$1" > "$1.tmp" && mv "$1.tmp" "$1"' _ {} \;
# 4. 修改 HTML 頭部聲明
# 或
HTTP 響應頭強制聲明 (Nginx/Apache/PHP):
# Nginx
charset utf-8;
# Apache
AddDefaultCharset utf-8
# PHP
header('Content-Type: text/html; charset=utf-8');
fileencoding=utf-8core.quotepath=false、gui.encoding=utf-8| 層級 | 驗證命令/操作 | 預期結果 |
|---|---|---|
| 服務端 | SHOW VARIABLES LIKE 'character_set%'; | 全部 utf8mb4 (除 filesystem/dir) |
| 庫/表/列 | SHOW CREATE TABLE t; | CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |
| 連接層 | SHOW VARIABLES LIKE 'character_set_connection'; | utf8mb4 |
| 應用寫入 | INSERT 中文 → SELECT HEX(col) | UTF-8 字節序列 (如 E4B8ADE69687) |
| 應用讀取 | Web 頁面顯示 / API 返回 JSON | 正常中文,無亂碼,HTTP Header charset=utf-8 |