字符集不一致是 MySQL 亂碼的核心原因。本文從服務端配置、庫表建立、連接參數、應用層編碼四個維度,構建全鏈路 UTF-8(utf8mb4)統一體系,並針對 GBK 遷移場景給出方案。
數據庫字符集 = 表字符集 = 列字符集 = 連接字符集 = 頁面/應用編碼
任何一環不一致皆可能導致亂碼。
my.cnf / my.ini)[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
init_connect = 'SET NAMES utf8mb4' -- 非超級用戶自動執行
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
關鍵點:
character-set-server 為新建庫默認字符集,必須在配置文件修改並重啟,SET GLOBAL 僅運行時生效,重啟失效。utf8 僅支援 BMP(3 字節),新項目強制 utf8mb4。default-character-set 已棄用,改用 character-set-server。-- 建庫
CREATE DATABASE `test2` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 建表
CREATE TABLE `t` (
`c` VARCHAR(100)
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- 修改現有庫表
ALTER DATABASE `old_db` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;
ALTER TABLE `old_t` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CONVERT TO 會轉換已有數據編碼;CHARACTER SET 僅修改默認值,不轉換現有數據。
SET NAMES utf8mb4; -- 等價於以下三條
SET character_set_client = utf8mb4;
SET character_set_connection = utf8mb4;
SET character_set_results = utf8mb4;
jdbc:mysql://192.168.0.5:3306/test?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai
對應關係: Java UTF-8 ↔ MySQL utf8mb4;Java GBK ↔ MySQL gbk;Java ISO-8859-1 ↔ MySQL latin1。
// PHP mysqli
$mysqli->set_charset("utf8mb4");
// PDO
$pdo = new PDO("mysql:host=...;dbname=...;charset=utf8mb4", $user, $pass);
// Python pymysql
conn = pymysql.connect(charset='utf8mb4')
mysqldump --default-character-set=gbk --no-create-info db > data.sqlTYPE=MyISAM → ENGINE=InnoDB DEFAULT CHARSET=utf8mb4mysql --default-character-set=utf8mb4 db < struct.sql → mysql --default-character-set=utf8mb4 db < data.sqlSELECT HEX(col), col FROM t WHERE col LIKE '%中文%' 檢查編碼正確性。| 現象 | 可能原因 | 排查命令 |
|---|---|---|
| 插入正常,查詢亂碼 | character_set_results 錯誤 | SHOW VARIABLES LIKE 'character_set_results'; |
| 插入即亂碼 | character_set_client/connection 錯誤 | SHOW VARIABLES LIKE 'character_set_client'; |
| 存儲截斷/報錯 | 列字符集與連接不匹配 | SHOW CREATE TABLE t; SHOW SESSION VARIABLES LIKE 'character_set%'; |
| Emoji 存成 ???? | 使用 utf8 而非 utf8mb4 | ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4; |
SELECT
@@character_set_server AS server,
@@character_set_database AS database,
@@character_set_client AS client,
@@character_set_connection AS connection,
@@character_set_results AS results,
@@collation_server AS collation_server,
@@collation_database AS collation_database,
@@collation_connection AS collation_connection;
確保以上全部為 utf8mb4 / utf8mb4_general_ci。