首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Debian/Ubuntu 系統 MySQL 8.0 徹底解決中文亂碼終極配置指南

     編輯:MySQL 資料庫相關知識

現象確認:為什麼會亂碼?

mysql> STATUS;
...
Server characterset:    latin1
Db     characterset:    latin1
Client characterset:    latin1
Conn.  characterset:    latin1
...

客戶端、連接、庫、表、結果集全鏈路 latin1,中文寫入時被按單字節截斷/錯誤編碼,讀出自然是亂碼 (??? 或 )。

核心原則:全鏈路 utf8mb4,拒絕 utf8 (僅支援 BMP 字符)

MySQL 8.0 預設已改為 utf8mb4_0900_ai_ci,但 Debian/Ubuntu 套件安裝後常保留舊配置兼容性,需顯式修正。

終極配置:/etc/mysql/my.cnf (或 /etc/mysql/mysql.conf.d/mysqld.cnf)

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
# 基礎字符集
character-set-server = utf8mb4
collation-server = utf8mb4_0900_ai_ci  # 或 utf8mb4_general_ci

# 強制客戶端握手字符集,防止客戶端指定 latin1
skip-character-set-client-handshake

# InnoDB 單表獨立表空間 (5.6+ 預設開啟,顯式聲明無害)
innodb_file_per_table = 1

# 避免隱式轉換導致索引失效
# explicit_defaults_for_timestamp = ON  # 5.6+ 預設 ON

關鍵差異說明:MySQL 5.5 vs 5.6+ vs 8.0

版本舊參數 (已廢棄/兼容)新標準參數備註
5.5 及之前default-character-set=utf8character-set-server=utf8僅支援 utf8 (3字節),Emoji 存不進
5.6 / 5.7default-character-set=utf8character-set-server=utf8mb4建議 utf8mb4,collation 用 utf8mb4_general_ci
8.0+不支援 default-character-set 在 [mysqld]character-set-server=utf8mb4
collation-server=utf8mb4_0900_ai_ci
預設校對規則更新,支援更準確排序

注意:舊教程常見 default-character-set=utf8 放在 [mysqld] 下,8.0 會導致啟動報錯 unknown variable,務必改用 character-set-server。

驗證步驟

  1. 重啟服務:systemctl restart mysql (或 service mysql restart)
  2. 進入檢查:
    mysql> SHOW VARIABLES LIKE 'character_set_%';
    mysql> SHOW VARIABLES LIKE 'collation_%';
    
  3. 預期輸出:所有 character_set_* 均為 utf8mb4,collation_* 為 utf8mb4_0900_ai_ci (或 general_ci)。
  4. 建庫建表驗證:
    CREATE DATABASE `test_db` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
    USE `test_db`;
    CREATE TABLE `t` (`c` VARCHAR(20)) CHARSET=utf8mb4;
    INSERT INTO `t` VALUES ('測試😀Emoji');
    SELECT * FROM `t`; -- 正常顯示
    

應用層連接配置 (同樣關鍵)

  • JDBC:jdbc:mysql://host:3306/db?characterEncoding=utf8mb4&useSSL=false&serverTimezone=Asia/Shanghai (8.0 驅動可省略 characterEncoding)
  • Python (PyMySQL/mysqlclient):charset='utf8mb4'
  • PHP (PDO):charset=utf8mb4 in DSN
  • Go (go-sql-driver/mysql):charset=utf8mb4,utf8 in DSN

避坑清單

  1. **只改庫/表字符集,不改配置文件** → 新連接仍用 latin1,舊資料雖可轉碼,新寫入依然亂碼。
  2. **用 utf8 而非 utf8mb4** → Emoji、生僻字存入報錯 Incorrect string value 或變 ?。
  3. **應用層連接未指定 charset** → 驅動預設可能 latin1,導致「庫是 utf8mb4,寫入卻亂碼」。
  4. **修改配置後未重啟 MySQL** → 配置不生效。
  5. **Debian/Ubuntu 多配置文件機制** → 改錯文件 (如改 /etc/mysql/my.cnf 實際讀 /etc/mysql/mysql.conf.d/mysqld.cnf),用 mysqld --verbose --help | grep -A1 'Default options' 確認生效文件順序。

歷史資料修復 (已寫入 latin1 的中文)

-- 1. 確認現狀
SELECT HEX(`col`), `col` FROM `tbl` WHERE `col` LIKE '%??%';

-- 2. 雙重轉碼法 (latin1 -> 二進制 -> utf8mb4)
UPDATE `tbl` SET `col` = CONVERT(CAST(CONVERT(`col` USING latin1) AS BINARY) USING utf8mb4);

-- 3. 或直接 ALTER TABLE 轉換 (會鎖表,大表慎用)
ALTER TABLE `tbl` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved