MySQL 編碼問題是開發者的永恆痛點。本文基於大量實戰經驗,揭示編碼亂碼的核心邏輯:「你用什麼編碼寫入,就得用什麼編碼讀出」。無需複雜理論,掌握這一核心原則配合實操技巧,徹底解決亂碼。
寫入端編碼 = 讀取端編碼 = 前端頁面編碼,三者一致即無亂碼。MySQL 內部儲存的是位元組流,不會主動轉碼。
必須在 PHP 層轉碼:
// 寫入前:UTF-8 → GB2312
$gbk_str = iconv('UTF-8', 'GB2312//IGNORE', $utf8_str);
mysql_query("INSERT INTO t (c) VALUES ('$gbk_str')");
// 讀取後:GB2312 → UTF-8
$utf8_str = iconv('GB2312', 'UTF-8//IGNORE', $row['c']);
// 或 mb_convert_encoding($row['c'], 'UTF-8', 'GB2312')
phpMyAdmin 內部檔案為 UTF-8 編碼,因此:
SET NAMES 'gb2312' (不確定有效)iconv('UTF-8', 'GB2312', $str)[client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4 [mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_general_ci init_connect = 'SET NAMES utf8mb4'
重點:MySQL 5.5+ 請用 utf8mb4 而非 utf8 (後者僅支援 3 字節,無法存 Emoji)。
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8mb4", 'user', 'pass', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
]);
// 或 mysqli
$mysqli->set_charset('utf8mb4'); // 關鍵!等同 SET NAMES utf8mb4
| 誤區 | 真相 |
|---|---|
| 修改資料表 CHARSET 就能修好亂碼 | 錯!資料已寫入,ALTER TABLE 只影響新資料,舊資料位元組不變 |
| MySQL 會自動轉碼 | 錯!MySQL 只比對 connection charset 與 column charset,不匹配才轉碼 |
| utf8 就夠了 | utf8mb4 才是真正的 UTF-8,支援 4 字節字符 (Emoji、生僻字) |
MySQL 編碼亂碼本質是編碼不一致。解決三步曲:1. 統一前端/PHP/連線編碼為 utf8mb4、2. 連線建立即執行 SET NAMES utf8mb4、3. 歷史資料用 iconv 遷移。拒絕在 MySQL 層設定花招,源頭統一才是王道。