MySQL 4.1 引入了多層級字符集支持(服務器、數據庫、表、列),但眾多 PHP 應用(如 WordPress)未區分版本差異,且 latin1 作為默認字符集掩蓋了中文環境下的潛在問題。主要成因有四:
latin1 默認編碼在單字節西文環境下無感,卻導致多字節中文存儲與讀取不一致。字符集可分別在四個層級指定,優先級由高到低:
ALTER TABLE t MODIFY c VARCHAR(10) CHARSET utf8CREATE TABLE t (...) DEFAULT CHARSET utf8CREATE DATABASE db DEFAULT CHARSET utf8my.ini default-character-set → 啟動參數 --default-character-set若低層級未顯式指定,則向上繼承。理解此繼承鏈是排查亂碼的關鍵。
SET NAMES客戶端與服務器交互時,必須聲明三個連接變量:
character_set_client:客戶端發送數據編碼character_set_connection:服務器接收後轉換目標編碼character_set_results:服務器返回結果編碼簡寫命令:SET NAMES 'utf8' 等同於同時設置以上三者為 UTF-8。此語句必須在建立連接後、執行任何查詢前立即執行。
[mysqld]
default-character-set = utf8
character-set-server = utf8
collation-server = utf8_general_ci
init_connect = 'SET NAMES utf8'
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$mysqli->set_charset('utf8'); // 推薦 mysqli 面向對象方式
// 或 PDO
$pdo = new PDO('mysql:host=localhost;dbname=db;charset=utf8', 'user', 'pass');
CREATE DATABASE mydb DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE mytable (
id INT PRIMARY KEY,
name VARCHAR(50)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
| 現象 | 可能原因 | 排查方向 |
|---|---|---|
| 存入中文顯示 ??? | 表/列字符集為 latin1 | 檢查 SHOW CREATE TABLE,執行 ALTER TABLE ... CONVERT TO CHARSET utf8 |
| 讀出中文變亂碼 | 連接層未 SET NAMES | 確認 PHP 連接代碼執行了 set_charset |
| 部分正常部分亂碼 | 混合了不同編碼的導入數據 | 檢查數據來源編碼,統一轉換後再導入 |
MySQL 4.1 編碼問題本質是「配置不一致」導致的編碼轉換錯誤。解決核心在於:服務端默認 UTF-8、連接層強制 SET NAMES utf8、建表顯式指定 CHARSET、應用層統一 UTF-8。建立標準化部署清單,可徹底杜絕亂碼困擾。