中文亂碼是MySQL開發中最高頻的痛點。本文從字符集編碼原理出發,剖析亂碼產生的四大核心環節,提供「全鏈路UTF-8」標準化解決方案,覆蓋服務端配置、連接初始化、表結構定義、應用層代碼、遷移修復五大場景,助你一次性徹底告別亂碼。
latin1,無法存儲中文latin1,寫入讀取雙向轉碼錯位[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4' # 非超級用戶自動執行
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqldump]
default-character-set = utf8mb4
重啟驗證:
SHOW VARIABLES LIKE 'character_set_%';
SHOW VARIABLES LIKE 'collation_%';
-- 期望全部為 utf8mb4 / utf8mb4_unicode_ci
-- 創建數據庫
CREATE DATABASE biz_db
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- 創建表(顯式指定,不依賴繼承)
CREATE TABLE users (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL COMMENT '用戶名',
bio VARCHAR(500) COMMENT '簡介'
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci
COMMENT='用戶表';
-- 修改現有表/列
ALTER TABLE old_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE old_table MODIFY COLUMN col_name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
原則:每次建立連接後,執行業務SQL前,必須先執行
SET NAMES utf8mb4;
-- 等價於:
SET character_set_client = utf8mb4;
SET character_set_connection = utf8mb4;
SET character_set_results = utf8mb4;
| 語言/框架 | 最佳實踐代碼 |
|---|---|
| PHP (PDO) | $pdo = new PDO("mysql:host=...;dbname=...;charset=utf8mb4", $user, $pass); (DSN中指定charset,PHP 5.3.6+) |
| PHP (mysqli) | $mysqli->set_charset("utf8mb4"); (連接對象創建後立即調用) |
| Java (JDBC) | url=jdbc:mysql://host:3306/db?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai |
| Python (PyMySQL) | conn = pymysql.connect(..., charset='utf8mb4') |
| Go (go-sql-driver/mysql) | dsn := "user:pass@tcp(host:3306)/db?charset=utf8mb4&parseTime=True&loc=Local" |
| Node.js (mysql2) | const pool = mysql.createPool({..., charset: 'utf8mb4'}); |
| C# (MySqlConnector) | connStr = "Server=...;Database=...;Uid=...;Pwd=...;Charset=utf8mb4;"; |
<meta charset="UTF-8">Content-Type: text/html; charset=UTF-8<form accept-charset="UTF-8"># 1. 導出數據(指定源編碼)
mysqldump -u root -p --default-character-set=gbk --no-create-info db_name > data.sql
# 2. 修改建表腳本為 utf8mb4
# 3. 轉換數據文件編碼
iconv -f gbk -t utf-8 data.sql > data_utf8.sql
# 4. 導入新庫
mysql -u root -p --default-character-set=utf8mb4 new_db < data_utf8.sql
config.inc.php:$cfg['DefaultCharset'] = 'utf8mb4';utf8mb4SET NAMES utf8mb4-- 情況:UTF-8數據被當作latin1寫入(雙重編碼)
-- 現象:中文變為 "䏿" 類似字符
UPDATE t SET col = CONVERT(CAST(CONVERT(col USING latin1) AS BINARY) USING utf8mb4);
-- 原理:latin1解碼獲取原始字節 → 二進制 → utf8mb4解碼還原
-- 1. 寫入測試數據(含生僻字、Emoji)
INSERT INTO test_tbl (txt) VALUES ('中文測試😀🎉'), ('不道可否囉'), ('𠮷野屋');
-- 2. 讀取驗證
SELECT txt, HEX(txt), CHAR_LENGTH(txt), LENGTH(txt) FROM test_tbl;
-- HEX 應為 UTF-8 字節序列
-- CHAR_LENGTH = 字符數,LENGTH = 字節數
-- 3. 命令行客戶端驗證
mysql --default-character-set=utf8mb4 -e "SELECT * FROM test_tbl;"
utf8 (MySQL別名,實為 utf8mb3,不支持Emoji/生僻字) → ✅ 全量使用 utf8mb4SET NAMES → ✅ 應用層連接建立後必執行