字符集編碼不一致是 MySQL 亂碼、數據截斷、排序錯誤的首要原因。本文系統整理 MySQL 字符集相關的所有核心操作:查看支援編碼、資料庫/表/欄位級別的創建與修改、會話級別動態設置、驗證方法,助您徹底解決編碼難題。
-- 列出所有支援字符集
SHOW CHARACTER SET;
-- 查看特定字符集詳細資訊
SHOW CHARACTER SET LIKE 'utf8%';
+---------+------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+------------------+---------------------+--------+
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_general_ci | 4 |
+---------+------------------+---------------------+--------+
-- 查看字符集的所有排序規則
SHOW COLLATION LIKE 'utf8%';
-- 1. 實例/會話級別系統變量
SHOW VARIABLES LIKE '%char%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 | -- 客戶端發送語句編碼
| character_set_connection | utf8mb4 | -- 連接層編碼
| character_set_database | utf8mb4 | -- 當前資料庫預設編碼
| character_set_results | utf8mb4 | -- 結果集返回編碼
| character_set_server | utf8mb4 | -- 服務端預設編碼
| character_set_system | utf8 | -- 系統標識符編碼(固定)
| character_sets_dir | /usr/share/mysql/charsets/ | -- 字符集文件目錄
+--------------------------+----------------------------+
-- 2. 資料庫編碼
SHOW CREATE DATABASE dbtest;
-- 或
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='dbtest';
-- 3. 表編碼
SHOW CREATE TABLE tbtest;
-- 4. 欄位編碼
SHOW FULL COLUMNS FROM tbtest;
-- 或
SELECT CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='dbtest' AND TABLE_NAME='tbtest' AND COLUMN_NAME='email';
-- 設置服務端預設編碼(需重啟永久生效,建議改配置檔)
SET character_set_server = utf8mb4;
-- 設置客戶端發送編碼
SET character_set_client = gbk;
-- 設置結果集返回編碼
SET character_set_results = gbk;
-- 一鍵設置三大核心變量(最常用)
SET NAMES utf8mb4;
-- 等價於:
SET character_set_client = utf8mb4;
SET character_set_connection = utf8mb4;
SET character_set_results = utf8mb4;
-- 僅設置連接編碼
SET CHARACTER SET utf8mb4;
-- 等價於:
SET character_set_client = utf8mb4;
SET character_set_results = utf8mb4;
SET collation_connection = utf8mb4_general_ci;
-- 1. 創建資料庫指定編碼(注意:utf8 不能寫成 utf-8)
CREATE DATABASE dbtest
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
-- 2. 修改資料庫編碼(僅影響後續新建表)
ALTER DATABASE dbtest
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
-- 3. 刪除資料庫
DROP DATABASE IF EXISTS dbtest;
-- 1. 創建表指定編碼(表預設編碼 + 欄位覆蓋)
CREATE TABLE tbtest (
id INT(10) AUTO_INCREMENT,
user_name VARCHAR(60) CHARACTER SET gbk COLLATE gbk_chinese_ci, -- 欄位級別覆蓋
email VARCHAR(60),
PRIMARY KEY (id)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 2. 修改表預設編碼(僅影響後續新增欄位)
ALTER TABLE tbtest
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
-- 注意:修改表編碼不會自動轉換現有欄位數據!
MODIFY COLUMN ... CHARACTER SET utf8mb4 會嘗試轉換現有數據CHANGE COLUMN ... CHARACTER SET utf8mb4 同樣會轉換數據ALTER TABLE ... CHARACTER SET utf8mb4 僅修改表預設值,不轉換現有欄位
-- 正確修改欄位編碼並轉換數據(推薦)
ALTER TABLE tbtest
MODIFY email VARCHAR(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 或使用 CHANGE(需重複欄位名)
ALTER TABLE tbtest
CHANGE email email VARCHAR(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 批次轉換全表所有字符串欄位(生產環境謹慎,先備份!)
-- 此腳本需根據實際表結構生成
SELECT CONCAT('ALTER TABLE ', TABLE_NAME, ' MODIFY ', COLUMN_NAME, ' ',
COLUMN_TYPE, ' CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'dbtest'
AND CHARACTER_SET_NAME != 'utf8mb4'
AND DATA_TYPE IN ('char','varchar','text','enum','set');
-- 1. 查看欄位實際編碼
SELECT CHARSET(email) FROM tbtest;
-- 或
SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='dbtest' AND TABLE_NAME='tbtest';
-- 2. 測試寫入/讀取
INSERT INTO tbtest (user_name, email) VALUES ('測試', 'test@example.com');
SELECT * FROM tbtest;
-- 3. 檢查十六進制內容(確認存儲編碼)
SELECT HEX(email), HEX(user_name) FROM tbtest;
-- utf8mb4 中文佔 3-4 bytes,gbk 佔 2 bytes
[mysqld]
# 服務端預設編碼
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci
# 避免客戶端編碼不匹配
skip-character-set-client-handshake
# 強制忽略客戶端傳來的字符集聲明,統一使用服務端設置
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqldump]
default-character-set = utf8mb4
| 特性 | utf8 (utf8mb3) | utf8mb4 |
|---|---|---|
| 最大字符長度 | 3 bytes | 4 bytes |
| Emoji 支援 | ❌ 不支援 | ✅ 完整支援 |
| 生僻字支援 | 部分缺失 | 完整 Unicode |
| 索引長度限制 | 767 bytes (單列) | 需配合 innodb_large_prefix |
| 儲存空間 | 略小 | 略大 (ASCII 相同) |
| 推薦版本 | MySQL 5.5 之前 | MySQL 5.5.3+ 強烈推薦 |
character_set_results 錯誤 → SET NAMES utf8mb4character_set_client 錯誤 → 連接字串指定 charset=utf8mb4utf8mb4_general_ci 或 utf8mb4_unicode_ci字符集問題的核心原則:全鏈路一致。從客戶端連接、會話變量、資料庫預設、表預設、欄位實際、結果返回,每一環都必須統一為 utf8mb4。新專案請直接採用 utf8mb4,存量專案請謹慎規劃轉換窗口並充分測試。