UTF-8 亂碼是 MySQL 開發者的「成人禮」。本文從字符集傳輸鏈路原理出發,給出配置文件、建表語句、連接代碼三層徹底修復方案,並解釋為什麼 cmd.exe 終端顯示亂碼屬正常現象。
一次完整的寫入/讀取涉及 4 個關鍵節點:
任意節點非 UTF-8,即產生「雙重編碼」或「解碼錯誤」→ 亂碼。
SHOW VARIABLES LIKE 'character%';
SHOW VARIABLES LIKE 'collation_%';
重點關注 character_set_client、connection、results 是否為 utf8(或 utf8mb4)。
[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'
建議: 使用 utf8mb4 而非 utf8,完整支持 Emoji 與生僻字。修改後 必須重啟 mysqld。
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE TABLE t (c VARCHAR(255)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
列級 COLLATE 可省略,繼承表級預設。
PHP (mysqli/PDO):
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$mysqli->set_charset('utf8mb4'); // 必須在查詢前調用
// PDO
$pdo = new PDO('mysql:host=localhost;dbname=db;charset=utf8mb4', 'user', 'pass');
舊版 mysql_* 函數(已棄用):
mysql_query("SET NAMES utf8mb4");
Web 頁面:
<meta charset="utf-8">
header('Content-Type: text/html; charset=utf-8');
中文 Windows 預設代碼頁 CP936 (GBK),無法顯示完整 UTF-8。在 cmd 執行 mysql 客戶端看到亂碼屬正常,不代表數據錯誤。解決:
chcp 65001 並設置字體為 TrueType(Consolas)。SET NAMES utf8mb4(或驅動原生 charset 參數)。INSERT ... VALUES ('測試😀'),多端查看一致。亂碼本質是「編碼協議不一致」。統一 配置層 → 存儲層 → 連接層 → 展示層 四層為 utf8mb4,即可一勞永逸。拒絕「碰運氣式」修復,建立標準化初始化腳本,新實例一鍵合規。