數據庫字符集 = 表/列字符集 = 連接字符集 = 頁面字符集
任一環節不一致即產生亂碼。
CREATE DATABASE dbname DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
推薦 utf8mb4:支持 Emoji、完整 Unicode,utf8 只是 utf8mb3 別名。
CREATE TABLE test (
id INT PRIMARY KEY,
name VARCHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
// mysqli
$conn = mysqli_connect($host, $user, $pass, $db);
mysqli_set_charset($conn, 'utf8mb4');
// PDO
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass);
$pdo->exec("SET NAMES utf8mb4");
$conn = mysql_connect($host, $user, $pass);
mysql_query("SET NAMES 'utf8mb4'"); // 讀寫統一
mysql_select_db($db, $conn);
String url = "jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai";
conn = pymysql.connect(host=host, user=user, password=pass, db=db, charset='utf8mb4')
mysql_set_character_set(mysql, "utf8mb4");
-- 1. 檢查庫字符集 SHOW CREATE DATABASE dbname; -- 2. 檢查表字符集 SHOW CREATE TABLE tablename; -- 3. 檢查列字符集 SHOW FULL COLUMNS FROM tablename; -- 4. 檢查連接字符集 SHOW VARIABLES LIKE 'character_set_%'; -- 關鍵:character_set_client/connection/results 必須均為 utf8mb4 -- 5. 檢查數據實際存儲 SELECT HEX(name) FROM test WHERE id=1; -- 中文「測試」UTF-8 編碼為 E6B58BE8AF95(6 字節)
| 現象 | 原因 | 修正 |
|---|---|---|
| ??? / | 連接字符集未設置/錯誤 | 執行 SET NAMES utf8mb4 |
| 涓婁竴娆℃槸 (亂碼但長度固定) | UTF-8 數據被 Latin1 讀取 | 連接層指定 utf8mb4 |
| 娴嬭瘯 (UTF-8 被 GBK 讀取) | 頁面/連接編碼不匹配 | 統一 utf8mb4 |
| Emoji 變 ? 或截斷 | 使用 utf8 (utf8mb3) | 全鏈路升級 utf8mb4 |
-- 1. 庫級 ALTER DATABASE dbname CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci; -- 2. 表級(含列級聯轉換) ALTER TABLE tablename CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 3. 僅修改表默認(不轉換現有列) ALTER TABLE tablename CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;
亂碼本質是**編碼/解碼不匹配**。落地執行:**新庫全鏈路 utf8mb4、舊庫 CONVERT TO 遷移、連接層強制 SET NAMES、頁面 meta charset=utf-8**。做到這四點,中文亂碼徹底消失。