MySQL 4 升級到 5 時,預設字元集從 latin1 變更為 UTF-8,導致歷史資料出現亂碼。本文記錄透過 mysqldump 指定 latin1 匯出、替換字元集、重新匯入的完整修復流程,並補充應用層連線字元集設定。
mysql> SHOW VARIABLES LIKE '%char%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
+--------------------------+----------------------------+
伺服器層仍為 latin1,但系統字元集為 utf8,導致存儲與顯示不一致。
mysqldump -hlocalhost -ueygle -p --default-character-set=latin1 blog > blog.sql
打開 blog.sql 確認中文正常顯示(此時檔案實際為 latin1 編碼但視覺正確)。
vim blog.sql
:%s/latin1/utf8/g
將所有 CHARSET=latin1、COLLATE=latin1_* 替換為 utf8 對應值。
mysql -hlocalhost -ueygle -p eyglenew < blog.sql
mysql> SHOW VARIABLES LIKE '%char%';
+--------------------------+----------------------------+
| character_set_database | utf8 | ← 已變更
| character_set_server | latin1 | ← 伺服器層未變,但庫/表已為 utf8
+--------------------------+----------------------------+
資料庫、資料表、欄位字元集均為 utf8,中文顯示正常。
資料庫為 UTF-8 時:
$link = mysql_connect($host, $user, $pass);
mysql_query("SET NAMES 'UTF8'");
mysql_query("SET CHARACTER SET UTF8");
mysql_query("SET CHARACTER_SET_RESULTS='UTF8'");
資料庫為 GBK 時:
mysql_query("SET NAMES 'GBK'");
SET NAMES charset 等同於同時設定 character_set_client、character_set_connection、character_set_results 三個會話變數。
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
修改後重啟 MySQL 生效。建議使用 utf8mb4 完整支援 4 位元組字元(Emoji、生僻字)。
--default-character-set=latin1latin1 替換為 utf8/utf8mb4CHARACTER SET utf8mb4SET NAMES utf8mb4