中文亂碼問題看似簡單,實則涉及 Web 前端、後端編碼、JDBC 連接參數、MySQL 多層字符集設定。本文以一個真實 JavaEE 專案案例為主線,展示從「發現亂碼」到「定位資料庫層」再到「逐層修正 Server/Database/Table/Column 字符集」的完整排查思路與操作步驟。
userName 欄位存入 ????
mysql> STATUS;
--------------
Server characterset: latin1
Db characterset: latin1
Client characterset: latin1
Conn. characterset: latin1
--------------
**結論**:四層均為 latin1,中文必定亂碼。
MySQL Server Instance Configuration WizardDetailed Configuration → Developer Machine → Multifunctional Database(第三項)gbk(或 utf8)結果:Server/Client/Conn. 變為 gbk,但 Db characterset 仍為 latin1。
[mysqld]
default-character-set = gbk
character-set-server = gbk
[client]
default-character-set = gbk
重啟服務,效果同方案 A。
ALTER DATABASE steven CHARACTER SET gbk;
再次 STATUS,四層皆為 gbk。此時若無歷史資料,通常已解決。
插入中文報錯:
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'userName' at row 1
檢查表結構:
SHOW CREATE TABLE t_user;
-- 發現:DEFAULT CHARSET=latin1,欄位 CHARACTER SET latin1
**根因**:Database 已改為 gbk,但既有表/欄位仍為 latin1。中文字符在 gbk 佔 2 字節,latin1 視為 2 個字符,導致長度超過 VARCHAR(100) 限制(實際存 200 字節)。
DROP TABLE t_user;
CREATE TABLE t_user (
userId INT PRIMARY KEY AUTO_INCREMENT,
userName VARCHAR(100) NOT NULL,
age INT,
birthday DATETIME,
isVip BOOLEAN
) DEFAULT CHARSET=gbk;
ALTER TABLE t_user CHARACTER SET gbk;
ALTER TABLE t_user MODIFY userName VARCHAR(100) CHARACTER SET gbk;
轉換後再次插入,中文正常顯示。
character-set-server = utf8mb4(現代建議)或 gbk/utf8。ALTER DATABASE db_name CHARACTER SET utf8mb4。ALTER TABLE tbl CONVERT TO CHARACTER SET utf8mb4(轉換資料)或 MODIFY COLUMN ... CHARACTER SET utf8mb4。characterEncoding=utf8mb4 或執行 SET NAMES utf8mb4。SHOW VARIABLES LIKE 'character_set%'、SHOW CREATE TABLE、實際寫讀測試。
SET NAMES 'gbk'; -- 相當於設定 client/connection/results
SET CHARACTER_SET_CLIENT = gbk;
SET CHARACTER_SET_RESULTS = gbk;
SET CHARACTER_SET_CONNECTION = gbk;
SHOW CREATE TABLE t_user;
ALTER DATABASE steven CHARACTER SET gbk;
ALTER TABLE t_user CHARACTER SET gbk;
ALTER TABLE t_user MODIFY userName VARCHAR(100) CHARACTER SET gbk;
CREATE TABLE t_user (...) DEFAULT CHARSET=gbk;
CONVERT TO 會重建表並轉換資料位元組,大表需用 pt-osc/gh-ost。SET NAMES 'gbk' 強制解碼(僅適用舊資料遷移場景)。