萬盛學電腦網

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

MySQL 字符集修改完整方案:會話級、全域配置、my.cnf 永久生效三層次

前言

字符集不匹配是 MySQL 亂碼的首要元兇。修改字符集分為**會話級臨時**、**全域動態**、**配置檔永久**三個層次,影響範圍與持久性不同。本文提供完整指令集、驗證方法與避坑指南,解決 `utf8`/`utf8mb4` 混用、連線字符集不一致等經典問題。

一、三層次修改指令對照

層次指令生效範圍持久性適用場景
會話級SET NAMES 'utf8mb4';
或分別 SET client/connection/results
當前連線斷線失效測試、臨時腳本、應用連線池初始化 SQL
全域動態SET GLOBAL character_set_server = 'utf8mb4';
SET GLOBAL character_set_database = 'utf8mb4';
全實例 (新連線)重啟失效緊急變更、驗證效果、無重啟權限
配置檔永久my.cnf / my.ini 修改 [client] [mysqld] 區段全實例 (含重啟)永久生產環境標準化部署

二、完整配置檔範例 (my.cnf / my.ini)

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4'  -- 非超級用戶連線自動執行

# 可選:強制所有表預設 utf8mb4 (新建表生效)
# skip-character-set-client-handshake  -- 忽略客戶端請求字符集,強制服務端字符集 (慎用)

關鍵點:

  • utf8mb4 > utf8:`utf8` 實為 `utf8mb3` (最多 3 字節),**無法存儲 Emoji、生僻字**;`utf8mb4` 完整支援 Unicode 4 字節。
  • collation 推薦:`utf8mb4_unicode_ci` (UCA 標準排序) 或 `utf8mb4_0900_ai_ci` (MySQL 8.0+ 預設,效能更好、支援更多語言)。
  • init_connect:自動為普通用戶連線設定字符集,**不影響 root/超級用戶** (避免鎖死)。

三、現有資料庫/表/欄位字符集遷移 (高風險操作,必先備份)

1. 資料庫級

ALTER DATABASE `db_name` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

2. 表級 (含欄位轉換)

-- 僅修改表預設字符集 (不影響現有欄位)
ALTER TABLE `tbl` DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

-- 連同現有字符欄位一併轉換 (會重建表,鎖表時間長,大表請用 pt-online-schema-change)
ALTER TABLE `tbl` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

3. 單欄位修改

ALTER TABLE `tbl` MODIFY `col` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

注意:`utf8mb4` 索引鍵長度限制 767 bytes (InnoDB 預設) 或 3072 bytes (開啟 `innodb_large_prefix` + `ROW_FORMAT=DYNAMIC/COMPRESSED`)。`VARCHAR(255)` utf8mb4 佔 768 bytes > 767,**必須縮減長度至 191 或開啟 large_prefix**。

四、驗證腳本

-- 1. 檢視實例級字符集變數
SHOW VARIABLES LIKE 'character_set_%';
SHOW VARIABLES LIKE 'collation_%';

-- 2. 檢視資料庫/表/欄位字符集
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='db_name';
SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA='db_name';
SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='db_name' AND TABLE_NAME='tbl';

-- 3. 實際寫入測試
INSERT INTO `tbl`(`col`) VALUES ('測試😀Emoji');
SELECT HEX(`col`), `col` FROM `tbl` WHERE `col` LIKE '%😀%';  -- 應顯示 F0 9F 98 80 (utf8mb4 4 字節)

五、應用層配置同步 (關鍵!)

框架/驅動配置位置關鍵參數
JDBC (MySQL Connector/J)JDBC URLjdbc:mysql://host:3306/db?characterEncoding=utf8mb4&connectionCollation=utf8mb4_unicode_ci
Python (PyMySQL/mysqlclient)連線參數charset='utf8mb4'
Go (go-sql-driver/mysql)DSNcharset=utf8mb4,utf8 (雙寫相容)
Node.js (mysql2)連線配置charset: 'utf8mb4'
PHP (PDO/mysqli)DSN / mysqli_set_charsetcharset=utf8mb4 / mysqli_set_charset($link, 'utf8mb4')

六、常見亂碼診斷流程圖

  1. 確認**資料實際儲存編碼** (用 HEX(col) 看位元組)。
  2. 確認**欄位/表/庫字符集定義** (`SHOW CREATE TABLE`)。
  3. 確認**連線字符集三件套** (`character_set_client/connection/results`) 是否一致 (`SHOW VARIABLES LIKE 'character_set_%'`)。
  4. 確認**應用層驅動配置** 是否顯式指定 `utf8mb4`。
  5. 若以上皆正確仍亂碼,檢查**中間層** (Proxy/中介軟體/ORM) 是否雙重編碼/解碼。

結語

字符集修改核心原則:**全鏈路統一 utf8mb4** (Server/Database/Table/Column/Connection/Application)。配置檔永久生效是基石,會話級 `SET NAMES` 是補充,遷移現有資料需謹慎規劃鎖表時間與索引長度限制。建立驗證腳本納入 CI/CD,杜絕亂碼回歸。

copyright © 萬盛學電腦網 all rights reserved