萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 中文亂碼終極解決方案:字符集診斷、修正與各語言連線配置

亂碼核心原理

MySQL 涉及 **4 層字符集** 流向:

  1. **儲存層**:Table/Column `CHARSET` (實際位元組編碼)。
  2. **連線層**:`character_set_client` (客戶端送請求編碼)、`character_set_connection` (Server 內部處理編碼)、`character_set_results` (Server 回傳結果編碼)。
  3. **終端/應用層**:終端機代碼頁 / 應用框架預設編碼。
  4. **系統層**:`character_set_server`、`character_set_database` (新建物件預設)。

**亂碼本質:任一層不匹配 → 編碼錯誤轉換 → 資料損壞/顯示異常。**

診斷指令:一鍵查看全鏈路編碼


SHOW VARIABLES LIKE 'character_set_%';
SHOW VARIABLES LIKE 'collation_%';

關鍵觀察:`client`、`connection`、`results`、`database`、`server` 是否一致 (建議全 `utf8mb4`)。

分層修正方案

層級 1:資料庫/資料表/欄位儲存編碼 (持久化)


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

-- 資料表級 (含現有欄位轉換)
ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 單欄位修改
ALTER TABLE tbl_name CHANGE col_name col_name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

注意: `CONVERT TO` 會重寫資料 (轉碼),大表耗時長、鎖表,維護窗口操作。

層級 2:連線編碼 (即時生效,Session 級)


-- 單一連線立即生效 (最常用)
SET NAMES utf8mb4; 
-- 等同於:
SET character_set_client = utf8mb4;
SET character_set_connection = utf8mb4;
SET character_set_results = utf8mb4;

-- 僅影響當前 Session,斷線失效。

層級 3:伺服器預設編碼 (永久,需重啟)


# my.cnf / my.ini [mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# [client] 區段 (影響 mysql 命令列等客戶端)
[client]
default-character-set = utf8mb4

# [mysql] 區段
[mysql]
default-character-set = utf8mb4

經典錯誤碼 1366 解決實錄

ERROR 1366 (HY000): Incorrect string value: '\xD5\xD4' for column 'name' at row 1

**原因**:Client 送 GBK 編碼字串 (`\xD5\xD4` = '中' GBK),但連線層 `character_set_client` 為 `utf8`,Server 嘗試以 UTF-8 解碼失敗。

**即時修正**:`SET NAMES gbk;` (告訴 Server 我送 GBK) → 插入成功。
**根治**:應用層連線字串指定 `charset=utf8mb4`,資料庫儲存統一 `utf8mb4`。

各語言/框架連線配置最佳實踐

環境配置範例
JDBC (MySQL Connector/J 8.0+)`jdbc:mysql://host:3306/db?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULL`
PHP (PDO)`$pdo = new PDO("mysql:host=...;dbname=...;charset=utf8mb4", $user, $pass);`
PHP (mysqli)`mysqli_set_charset($link, 'utf8mb4');`
Python (PyMySQL / mysqlclient)`charset='utf8mb4'` in connect()
Go (go-sql-driver/mysql)`user:pass@tcp(host:3306)/db?charset=utf8mb4&parseTime=True&loc=Local`
Node.js (mysql2)`charset: 'utf8mb4'` in createConnection()
Django (DATABASES)`'OPTIONS': {'charset': 'utf8mb4'}`
Spring Boot (application.yml)`url: jdbc:mysql://...?characterEncoding=utf8mb4&useSSL=false` + `hikari.connectionInitSql: SET NAMES utf8mb4`

utf8 vs utf8mb4 必知差異

  • `utf8` (MySQL 別名 `utf8mb3`):**僅支援 BMP 平面 (3 Bytes)**,無法儲存 Emoji (😀)、生僻字 (𠮷)、部分符號。
  • `utf8mb4`:**真正 UTF-8 (1-4 Bytes)**,完整支援 Unicode 所有字元。**新專案強制使用 utf8mb4**。

排查清單 (由近及遠)

  1. 應用連線參數 `charset=utf8mb4` / `SET NAMES utf8mb4`。
  2. 資料表/欄位 `CHARSET=utf8mb4` (`SHOW CREATE TABLE`)。
  3. 資料庫預設 `utf8mb4` (`SHOW CREATE DATABASE`)。
  4. 伺服器 `character-set-server=utf8mb4` (`my.cnf` 重啟生效)。
  5. 終端機/IDE/瀏覽器編碼設定為 UTF-8。
  6. 檔案本身編碼 (SQL 腳本、CSV) 為 UTF-8 (無 BOM 最佳)。
copyright © 萬盛學電腦網 all rights reserved