首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 中文亂碼徹底解決:連接層、庫表層、數據層三層編碼鏈路全鏈路修復

     編輯:MySQL 綜合教學

MySQL 中文亂碼徹底解決:連接層、庫表層、數據層三層編碼鏈路全鏈路修復

中文亂碼本質是「編碼鏈路不一致」:客戶端編碼 ≠ 連接編碼 ≠ 庫表編碼 ≠ 存儲編碼。本文從連接建立、庫表創建、寫入讀取三個階段,給出標準化修復動作與驗證清單,徹底終結「問號菱形、亂碼、截斷」三大癥狀。

編碼鏈路全景圖


[應用代碼字符集] → [JDBC/驅動 connectionEncoding] → [MySQL 連接 character_set_client/connection/results] 
                                                    ↓
                                          [庫默認字符集] → [表默認字符集] → [列字符集]
                                                    ↓
                                          [存儲引擎頁面編碼] → [磁盤字節序列]

階段一:連接建立 — 統一連接編碼


-- 方式 1:連接後立即執行(所有客戶端通用)
SET NAMES utf8mb4;  -- 等價於 SET character_set_client/connection/results = utf8mb4

-- 方式 2:JDBC URL 參數(Java 應用推薦)
jdbc:mysql://host:3306/db?useUnicode=true&characterEncoding=utf8mb4&zeroDateTimeBehavior=convertToNull

-- 方式 3:my.cnf 全局默認(需重啟)
[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'  -- 非 super 用戶自動執行

驗證: SHOW VARIABLES LIKE 'character_set_%'; 客戶端/連接/結果均為 utf8mb4。

階段二:庫表創建 — 顯式指定字符集


-- 庫級
CREATE DATABASE mydb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 或修改現有庫
ALTER DATABASE mydb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

-- 表級
CREATE TABLE t1 (
  id INT PRIMARY KEY,
  name VARCHAR(50)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 或修改現有表(僅影響新增列)
ALTER TABLE t1 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

-- 列級(徹底修復現有列)
ALTER TABLE t1 MODIFY name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 或批量生成
SELECT CONCAT('ALTER TABLE ', TABLE_NAME, ' MODIFY ', COLUMN_NAME, ' ', COLUMN_TYPE, ' CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'mydb' AND CHARACTER_SET_NAME != 'utf8mb4';

階段三:寫入讀取 — 單引號轉義與驗證


-- 單引號轉義規則:' → \'
-- 應用層處理(Java 示例)
String safeVal = val.replace("\\", "\\\\").replace("'", "\\'");

-- 或使用 PreparedStatement 完全避免轉義問題
PreparedStatement ps = conn.prepareStatement("INSERT INTO t1(name) VALUES (?)");
ps.setString(1, userInput);  // 驅動自動處理編碼與轉義
ps.executeUpdate();

常見癥狀 → 根因 → 修復對照表

癥狀典型根因修復動作
插入「???」/「」連接編碼為 latin1,無法表示中文SET NAMES utf8mb4 / JDBC characterEncoding=utf8mb4
插入「中文」讀出「涓浣」寫入 utf8mb4,讀取按 latin1 解碼統一讀寫連接編碼為 utf8mb4
Emoji 存成「????」/報錯庫表字符集為 utf8 (3 字節),不支持 4 字節 Emoji全鏈路升級 utf8mb4,含列級 MODIFY
截斷「中文...」列長度按字節計算,utf8mb4 中文佔 3-4 字節超過 VARCHAR(n)擴大列長度或改用 TEXT
單引號導致 SQL 語法錯誤拼接 SQL 未轉義強制使用 PreparedStatement

驗證清單(部署後必跑)


-- 1. 連接編碼
SHOW VARIABLES LIKE 'character_set_%';
-- client/connection/results/database/server 均為 utf8mb4

-- 2. 庫表字符集
SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_COLLATION 
FROM information_schema.TABLES 
WHERE TABLE_SCHEMA = 'mydb';

-- 3. 列字符集
SELECT TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'mydb' AND CHARACTER_SET_NAME != 'utf8mb4';

-- 4. 實測寫讀
INSERT INTO t1(name) VALUES ('測試Emoji😀');
SELECT name, HEX(name), CHAR_LENGTH(name), LENGTH(name) FROM t1 WHERE name LIKE '%測試%';
-- HEX 應顯示 E6B58BE8AF95F09F9880 (UTF-8 字節序列)

避坑指南

  1. utf8 ≠ utf8mb4: MySQL utf8 實為 utf8mb3,不支持 Emoji,新項目強制 utf8mb4。
  2. SET NAMES 僅對當前連接生效,連接池復用時必須在借出前執行(HikariCP connectionInitSql)。
  3. ALTER TABLE ... DEFAULT CHARSET 不修改現有列,必須逐列 MODIFY。
  4. mysqldump 導出默認 --default-character-set=utf8mb4,導入時目標庫必須同字符集。
  5. 排查亂碼時,HEX(column) 是唯一真理,肉眼不可信。

編碼一致性是系統工程,而非單點配置。建立「連接層統一、庫表層顯式、列層徹底、驗證層自動化」四層防線,中文亂碼將成為歷史。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved