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

JDBC 連接 MySQL 中文亂碼終極解決方案:從驅動到數據庫全鏈路排查

     編輯:MySQL 綜合教學

亂碼根因:字元集不一致的「木桶效應」

JDBC 寫入 MySQL 出現問號(???),本質是 客戶端編碼 → 連接層轉換 → 伺服器儲存 → 表/列定義 → 讀取回傳 任一環節字元集不匹配導致的資訊損失。UTF-8 為例,若某環節為 latin1/gbk,多位元組字符會被截斷或錯誤映射。

四層檢查清單:由內而外系統排查

第 1 層:MySQL 伺服器與數據庫級配置

-- 1. 查看當前字元集設置
SHOW VARIABLES LIKE '%char%';
SHOW VARIABLES LIKE '%collation%';

-- 關鍵變數預期值(UTF-8 方案)
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci  -- 或 utf8mb4_unicode_ci

修改配置文件永久生效

[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

關鍵點:utf8mb4 支援 4 位元組字符,utf8 實為 utf8mb3 僅支援 BMP 平面,生產環境強制 utf8mb4。

第 2 層:資料庫、表、列級定義

-- 檢查資料庫字元集
SHOW CREATE DATABASE db_name;

-- 檢查表字元集
SHOW CREATE TABLE table_name;

-- 檢查列字元集
SHOW FULL COLUMNS FROM table_name;

修正已存在物件

-- 資料庫級
ALTER DATABASE db_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;

-- 表級(僅影響新建列)
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

-- 列級精確修改
ALTER TABLE table_name MODIFY COLUMN col_name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

避坑:CONVERT TO 會重建表並轉換現有數據,大表請用 pt-online-schema-change 或維護窗口操作。

第 3 層:JDBC 連接字串與驅動版本

MySQL Connector/J 8.0+ (推薦)

jdbc:mysql://host:3306/db_name?
  characterEncoding=utf8mb4&
  useUnicode=true&
  connectionCollation=utf8mb4_general_ci&
  serverTimezone=Asia/Shanghai&
  useSSL=false&
  allowPublicKeyRetrieval=true
  • 8.0+ 無需 額外參數即可正確處理 utf8mb4
  • characterEncoding 指定客戶端編碼,驅動會發送 SET NAMES

舊版驅動 5.1.x (維護專案)

jdbc:mysql://host:3306/db_name?
  useUnicode=true&
  characterEncoding=utf8&
  connectionCollation=utf8_general_ci

⚠️ 5.1.x 不支援 utf8mb4,需升級驅動或接受 Emoji 無法儲存。

第 4 層:應用框架與連接池配置

Spring Boot / HikariCP

spring.datasource.url=jdbc:mysql://host:3306/db?characterEncoding=utf8mb4&useUnicode=true&serverTimezone=Asia/Shanghai
spring.datasource.hikari.connection-init-sql=SET NAMES utf8mb4 COLLATE utf8mb4_general_ci

Druid 連接池

druid.connectionProperties=useUnicode=true;characterEncoding=utf8mb4
# 或

  SET NAMES utf8mb4 COLLATE utf8mb4_general_ci

實戰排查流程圖

  1. 現象確認:問號 ??? 還是亂碼 ?前者為編碼截斷,後者為雙重編碼
  2. 驗證數據庫端:SELECT HEX(col), col FROM table WHERE id=? 查看實際儲存的十六進位
  3. 檢查連接參數:SHOW SESSION VARIABLES LIKE '%char%'; 在應用連接中執行
  4. 追蹤 SQL 執行:開啟 General Log 或使用 p6spy 攔截實際發送的 SQL
  5. 定位斷點:對比客戶端、連接、會話、資料庫、表、列六層字元集

常見陷阱與解決方案

場景症狀根因解決
Emoji 儲存失敗報錯 Incorrect string value列/表為 utf8 (mb3)ALTER TABLE ... CONVERT TO utf8mb4
讀取顯示亂碼中文變 或 ???讀取時字元集不匹配連接字串加 characterEncoding、檢查頁面/控制台編碼
Druid/Hikari 連接池重啟後正常,運行一段時間亂碼連接復用未重置字元集配置 connectionInitSqls 設置 SET NAMES
舊系統遷移歷史數據已為 latin1 儲存中文雙重編碼 latin1→utf8導出→修正編碼→導入,或 CONVERT TO 配合 BINARY 過渡

最佳實踐總結

  1. 全鏈路統一 utf8mb4:Server/Database/Table/Column/Connection/JVM/File.encoding
  2. 驅動升級 8.0+:原生支援、效能更好、安全修補
  3. 連接池初始化 SQL:SET NAMES utf8mb4 COLLATE utf8mb4_general_ci 保證每次獲取連接重置
  4. 頁面/控制台 UTF-8:HTML ``、IDE/終端編碼設置
  5. 監控告警:定期掃描非 utf8mb4 表、列,納入發布檢查清單

總結

JDBC 中文亂碼看似瑣碎,實則考驗對字元集全鏈路的掌控力。遵循「utf8mb4 全棧統一、驅動版本跟進、連接池初始化 SQL 兜底」三大原則,配合系統化排查流程,即可徹底根治。記住:預防勝於治療,新專案第一天就鎖定 utf8mb4。

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