latin1(實際存儲 UTF-8 位元組流)。SET NAMES utf8 讀取會亂碼。部分火星字無法在 GBK 表示,顯示 ?。
MySQL 以 latin1 解碼後的字串非合法 UTF-8,轉碼失敗全亂碼。
iconv -f latin1 -t UTF-8 無法正確處理「以 latin1 存儲的 UTF-8 位元組」。
Linux 終端下以 GB18030 讀取 latin1 導出檔,實際能正確還原中文與火星字,再轉 UTF-8 入庫。
mysqldump --default-character-set=latin1 -q --single-transaction \
-t db_collect table1 table2 > db_collect.sql
CREATE DATABASE db_collect2 DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 在 db_collect2 執行 db_collect.sql 的結構部分(去除數據),或用 SHOW CREATE TABLE 重建
export LANG=en_US
export CRT=default
sed -i 's/latin1/utf8mb4/g' db_collect.sql
iconv -f gb18030 -c -t UTF-8 db_collect.sql -o db_collect_utf8.sql
mysql -f db_collect2 < db_collect_utf8.sql
SELECT * FROM table1 WHERE name LIKE '%😀%'; 確認 Emoji 正常。<?php
$src = mysqli_connect('10.0.0.1', 'root', 'pwd', 'db_collect');
$dst = mysqli_connect('10.0.0.2', 'root', 'pwd', 'db_collect2');
mysqli_set_charset($src, 'latin1'); // 關鍵:以 latin1 讀取
mysqli_set_charset($dst, 'utf8mb4'); // 寫入 utf8mb4
mysqli_query($dst, "SET NAMES utf8mb4");
$res = mysqli_query($src, "SELECT id, name FROM table1");
while ($row = mysqli_fetch_assoc($res)) {
$name_utf8 = iconv('GB18030', 'UTF-8//IGNORE', $row['name']);
$name_utf8 = mysqli_real_escape_string($dst, $name_utf8);
mysqli_query($dst, "INSERT INTO table1 (id, name) VALUES ({$row['id']}, '$name_utf8')");
}
mysqli_close($src); mysqli_close($dst);
排程執行:export LANG=en_US.UTF-8 && php /opt/sync_latin1_to_utf8.php
characterEncoding=utf8mb4。my.cnf character-set-server=utf8mb4。