字符集 ≠ 編碼。同一個漢字「中」:
校驗程序直接比較**二進制字節序列**,編碼不同必然不相等。這不是數據不一致,是**表達形式不一致**。
核心原則: 應用程序建立連接時,**主備庫使用相同的連接字符集**(`SET NAMES charset`),與服務器端存儲字符集無關。
| 策略 | 連接字符集 | 適用條件 | 副作用 |
|---|---|---|---|
| 跟隨主庫 | utf8 / utf8mb4 | 主庫為權威源、應用層以 UTF-8 為標準 | 備庫 gbk 存儲需隱式轉換,極少數字符可能無法表示 (如 Emoji) |
| 跟隨備庫 | gbk | 歷史系統全鏈路 GBK、無 Emoji 需求 | 主庫 utf8mb4 數據含 4 字節字符時會報錯或截斷 |
| 統一為 utf8mb4 (推薦) | utf8mb4 | 新系統、需完整 Unicode 支持 | 備庫需 `ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4` 遷移 |
$dsnMaster = "mysql:host=master;dbname=test;charset=utf8mb4";
$dsnSlave = "mysql:host=slave;dbname=test;charset=utf8mb4"; // 統一!
$pdoM = new PDO($dsnMaster, 'user', 'pass');
$pdoS = new PDO($dsnSlave, 'user', 'pass');
$stmtM = $pdoM->query("SELECT col FROM tbl WHERE id=1");
$stmtS = $pdoS->query("SELECT col FROM tbl WHERE id=1");
$valM = $stmtM->fetchColumn();
$valS = $stmtS->fetchColumn();
// 此時二進制字節序列一致,直接比較即可
var_dump($valM === $valS); // true
連接字符集 ≠ 客戶端顯示字符集。終端/IDE/瀏覽器需設置為 UTF-8 顯示。若連接用 `utf8mb4` 但終端是 GBK,會看到亂碼,**但數據庫層面已正確**。