mysql> STATUS;
...
Server characterset: latin1
Db characterset: latin1
Client characterset: latin1
Conn. characterset: latin1
...
客戶端、連接、庫、表、結果集全鏈路 latin1,中文寫入時被按單字節截斷/錯誤編碼,讀出自然是亂碼 (??? 或 )。
MySQL 8.0 預設已改為 utf8mb4_0900_ai_ci,但 Debian/Ubuntu 套件安裝後常保留舊配置兼容性,需顯式修正。
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
# 基礎字符集
character-set-server = utf8mb4
collation-server = utf8mb4_0900_ai_ci # 或 utf8mb4_general_ci
# 強制客戶端握手字符集,防止客戶端指定 latin1
skip-character-set-client-handshake
# InnoDB 單表獨立表空間 (5.6+ 預設開啟,顯式聲明無害)
innodb_file_per_table = 1
# 避免隱式轉換導致索引失效
# explicit_defaults_for_timestamp = ON # 5.6+ 預設 ON
| 版本 | 舊參數 (已廢棄/兼容) | 新標準參數 | 備註 |
|---|---|---|---|
| 5.5 及之前 | default-character-set=utf8 | character-set-server=utf8 | 僅支援 utf8 (3字節),Emoji 存不進 |
| 5.6 / 5.7 | default-character-set=utf8 | character-set-server=utf8mb4 | 建議 utf8mb4,collation 用 utf8mb4_general_ci |
| 8.0+ | 不支援 default-character-set 在 [mysqld] | character-set-server=utf8mb4 collation-server=utf8mb4_0900_ai_ci | 預設校對規則更新,支援更準確排序 |
注意:舊教程常見 default-character-set=utf8 放在 [mysqld] 下,8.0 會導致啟動報錯 unknown variable,務必改用 character-set-server。
systemctl restart mysql (或 service mysql restart)mysql> SHOW VARIABLES LIKE 'character_set_%';
mysql> SHOW VARIABLES LIKE 'collation_%';
character_set_* 均為 utf8mb4,collation_* 為 utf8mb4_0900_ai_ci (或 general_ci)。CREATE DATABASE `test_db` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
USE `test_db`;
CREATE TABLE `t` (`c` VARCHAR(20)) CHARSET=utf8mb4;
INSERT INTO `t` VALUES ('測試😀Emoji');
SELECT * FROM `t`; -- 正常顯示
jdbc:mysql://host:3306/db?characterEncoding=utf8mb4&useSSL=false&serverTimezone=Asia/Shanghai (8.0 驅動可省略 characterEncoding)charset='utf8mb4'charset=utf8mb4 in DSNcharset=utf8mb4,utf8 in DSNIncorrect string value 或變 ?。/etc/mysql/my.cnf 實際讀 /etc/mysql/mysql.conf.d/mysqld.cnf),用 mysqld --verbose --help | grep -A1 'Default options' 確認生效文件順序。-- 1. 確認現狀
SELECT HEX(`col`), `col` FROM `tbl` WHERE `col` LIKE '%??%';
-- 2. 雙重轉碼法 (latin1 -> 二進制 -> utf8mb4)
UPDATE `tbl` SET `col` = CONVERT(CAST(CONVERT(`col` USING latin1) AS BINARY) USING utf8mb4);
-- 3. 或直接 ALTER TABLE 轉換 (會鎖表,大表慎用)
ALTER TABLE `tbl` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;