MySQL 中文亂碼核心在於「客戶端、連線層、伺服器端、儲存層」四層編碼一致。本文提供系統排查步驟、永久配置與各語言驅動最佳實務。
mysql> SHOW VARIABLES LIKE '%char%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 ← 常見問題點 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
-- 1. 修正資料庫預設編碼 (永久)
ALTER DATABASE db_name CHARACTER SET utf8;
-- 2. 設定客戶端送出編碼 (當前連線)
SET character_set_client = gbk; -- 或 utf8
-- 3. 設定結果集回傳編碼 (當前連線)
SET character_set_results = gbk; -- 或 utf8
[client]
default-character-set = utf8
[mysqld]
character-set-server = utf8
collation-server = utf8_general_ci
init_connect = 'SET NAMES utf8' # 非 super 用戶自動執行
[mysql]
default-character-set = utf8
| 環境 | 解決方案 |
|---|---|
| PHP (mysqli/PDO) | 連線後立即執行 SET NAMES utf8 / $mysqli->set_charset('utf8') / PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' |
| Java JDBC | 連線字串加參數 ?characterEncoding=utf8&useSSL=false,驅動自動處理 |
| Python MySQLdb/PyMySQL | charset='utf8' 參數或 cursor.execute('SET NAMES utf8') |
| Go database/sql | DSN 加 charset=utf8mb4,utf8 |
| MySQL Workbench / Navicat / DBeaver | 連線屬性 → 編碼選 UTF-8,工具自動發送 SET NAMES |
| CMD / 黑視窗 | chcp 65001 + SET NAMES utf8mb4 (支援 Emoji) |
my.cnf 不重啟服務 → 不生效。ALTER DATABASE 僅影響新表,舊表需逐表 ALTER TABLE ... CONVERT TO CHARACTER SET utf8。utf8 (MySQL 3 字節偽 UTF-8) 而非 utf8mb4 (真正 UTF-8),導致 Emoji/生僻字存入變 ??。建議全面遷移至 utf8mb4。