MySQL 字元集指定可精細到「庫、表、欄、連線」,但傳統應用多依賴預設值。理解七層預設傳遞鏈,才能從根源掌控編碼行為,避免「明明設定了 UTF-8 卻存成 latin1」的困擾。
latin1 (歷史遺留)my.cnf 中 default-character-set / character-set-server,未指定則繼承編譯期mysqld --character-set-server=utf8mb4,未指定則繼承配置檔character_set_server 固定為上層決定值CREATE DATABASE db 未指定 CHARSET → 繼承 character_set_serverUSE db → character_set_database 設為該庫預設字元集CREATE TABLE t 未指定 → 繼承 character_set_database (即資料庫預設)col VARCHAR(100) 未指定 → 繼承表預設字元集若完全不修改任何設定,全鏈路預設為 latin1。
現代安裝程式 (yum/apt/官方安裝器) 通常會在配置檔預設default-character-set = utf8或utf8mb4,這改變了第 2 層,進而影響後續所有層級。
SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%';
character_set_server | utf8mb4 character_set_database | utf8mb4 collation_server | utf8mb4_general_ci collation_database | utf8mb4_general_ci
character_set_server | latin1 character_set_database | latin1 collation_server | latin1_swedish_ci collation_database | latin1_swedish_ci
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 此庫及其下建表預設為 utf8mb4,無視 server 設定
CREATE TABLE t (c VARCHAR(100)) CHARACTER SET utf8mb4; -- 僅此表預設為 utf8mb4,不影響資料庫預設
CREATE TABLE t (
c1 VARCHAR(100), -- 繼承表預設
c2 VARCHAR(100) CHARACTER SET latin1 -- 強制 latin1
);
連線建立時,三個關鍵變數決定傳輸編碼:
character_set_client:客戶端發送 SQL 的編碼character_set_connection:Server 內部處理的編碼character_set_results:結果集返回給客戶端的編碼最佳實踐:連線建立後立即執行:
SET NAMES 'utf8mb4'; -- 等同同時設定以上三者
MySQL 字元集預設傳遞鏈:編譯 → 配置檔 → 啟動參數 → Server → Database → Table → Column,每層可透過顯式指定打破繼承。現代部署請在 my.cnf 設定 character-set-server = utf8mb4 固化第 2-4 層,連線層執行 SET NAMES utf8mb4 掌控第 8 層。理解此鏈路,編碼問題將不再是謎。