确认last_sql_error是否由字符集引发,需检查其是否含“cannot be converted from type 'varchar(1536)' to type 'varchar(2048) utf8mb4'”等提示;再比对主从show create table输出的charset与collation,核查复制线程的@@character_set_client和@@collation_connection,并用convert to统一表字符集,同步修正my.cnf中character-set-server与collation-server配置。

确认Last_SQL_Error是否由字符集引发
看到从库SHOW SLAVE STATUS\G中Last_SQL_Error包含类似cannot be converted from type 'varchar(1536)' to type 'varchar(2048) utf8mb4'或Incorrect string value: '\xF0\x9F\x92\xA9',基本可锁定字符集问题。别只扫一眼就动手改——先比对主从两端同一张表的建表语句:
- 主库执行:
SHOW CREATE TABLE your_db.your_table\G - 从库执行同样命令
- 逐行对比输出里的
DEFAULT CHARSET、字段定义中显式写的CHARACTER SET和COLLATE(不是character_set_database,它只是默认值)
检查复制线程自身的字符集上下文
复制线程本质是个特殊客户端连接,它的@@character_set_client和@@collation_connection决定如何解析 binlog 字节流。即使表结构一致,这两个变量不对也会触发Last_Errno: 1677:
- 在从库执行:
SELECT @@character_set_client, @@collation_connection; - 预期返回必须是
utf8mb4和utf8mb4_unicode_ci(与主库建表用的校对规则一致) - 若返回
latin1或utf8,说明复制线程正用错误编码读 binlog,此时改表也没用
统一表级字符集必须用CONVERT TO
ALTER TABLE ... MODIFY COLUMN或CHANGE COLUMN只改列定义,不转已有数据、不更新索引、不改其他列,同步时仍会报错:
- 安全做法是:
ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 漏掉
COLLATE很危险:MySQL 会 fallback 到utf8mb4_general_ci,而主库原表若用utf8mb4_unicode_ci,比较逻辑差异可能间接导致索引失效或条件误判 - 含外键或全文索引的表,
CONVERT TO可能失败,需提前验证;生产环境建议先删约束再加
服务端配置必须同步修正
只修当前报错表是治标。主从character_set_server不一致,新库/新表会自动继承不同默认字符集,问题迟早重现:
- 主从
my.cnf的[mysqld]段都加上:character-set-server = utf8mb4和collation-server = utf8mb4_unicode_ci - 重启 MySQL 生效;
SET GLOBAL character_set_server = 'utf8mb4'不持久,且只影响新连接,不能替代配置文件 - 所有 DDL 必须显式声明字符集,例如
CREATE TABLE t (c VARCHAR(10)) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
真正麻烦的是那些没显式声明字符集的旧表——主库按自己的character_set_database建表,binlog 不记录字符集信息,从库却按自己的默认值建同名表,结构从第一行就错了。这种隐式继承问题,必须靠配置+建表规范+全量表修复三者闭环,缺一不可。











