主从复制SQL线程中断——字符集砸出的坑
## 一、问题现场SQL 线程中断但表结构一致告警响起异步复制的 slave 端 SQL 线程中断了。查询表 replication_applier_status_by_worker检查报错信息SQLGreatSQL SELECT * FROM performance_schema.replication_applier_status_by_worker\G;*************************** 1. row ***************************SERVICE_STATE: OFFLAST_ERROR_NUMBER: 13146LAST_ERROR_MESSAGE: Worker 1 failed executing transactionf08e63fb-3b91-11f0-af59-5254d9b382e7:66192867 at master log binlog.000423, end_log_pos 115725003;Column 1 of table gsqldb_xxx.dynamic_yyy_log cannot be convertedfrom type varchar(128(bytes)) to type varchar(96(bytes) utf8mb3)...报错很直白事务66192867在回放时列类型转换失败。核对主从表结构SQLGreatSQL SHOW CREATE TABLE gsqldb_xxx.dynamic_yyy_log\G;CREATE TABLE dynamic_yyy_log (id bigint NOT NULL AUTO_INCREMENT COMMENT 自增ID,business_id varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 业务主键,serial varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 设备唯一编号,push_time datetime DEFAULT NULL COMMENT 上传时间,remark varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 备注,sort int DEFAULT 0 COMMENT 排序,create_by varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 创建人,edit_by varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 最后编辑人,time_created datetime NOT NULL COMMENT 记录创建时间,time_modified datetime NOT NULL COMMENT 记录修改时间,status varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 状态,operation varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 操作,version int DEFAULT 0 COMMENT 乐观锁,deleted int DEFAULT 0 COMMENT 逻辑删除,PRIMARY KEY (id) USING BTREE,KEY business_id (business_id) USING BTREE,KEY comp_business_id (serial) USING BTREE,KEY sort (sort) USING BTREE) ENGINEInnoDB AUTO_INCREMENT1083580 DEFAULT CHARSETutf8mb3 ROW_FORMATDYNAMIC;让人困惑的是主从两端的表结构完全一致business_id 都是 varchar(32) utf8mb3。那么SQL 线程到底在抗议什么---## 二、细看报错信息LAST\_ERROR\_MESSAGE 透露了什么把报错拆开看能看出两层关键信息1. **问题出在哪一列**报错说 Column 1。注意这里的列号从 0 开始编号所以 Column 1 对应的是表里的第二列——business_id。2. **直接原因是什么**cannot be converted from type varchar(128(bytes)) to type varchar(96(bytes) utf8mb3)。也就是 slave 在回放时发现 binlog 里记录的列长度128 字节和本地表定义96 字节对不上拒绝转换。到这里矛盾点已经浮现本地表定义里 business_id 是 varchar(32) utf8mb3怎么会转换 varchar(128(bytes))呢---## 三、大胆假设做了什么操作- slave 端是 varchar(32) utf8mb3。utf8mb3 每个字符最多占 3 字节32 个字符对应 96 字节——正好对应报错里的 varchar(96(bytes) utf8mb3)。- 但 master 端在 binlog slave 的 relaylog中记录的是 varchar(128(bytes))。128 不能被 3 整除却能被 4 整除商是32正好和varchar\(32\)对应。如果字符集是utf8mb4一个字符最多占 4 字节varchar(32) utf8mb4就是varchar(128(bytes))。由此可以合理推测 master 上发生过的操作master 端在 sql_log_binoff 的情况下把 business_id 改成了 utf8mb4 执行了insert操作binlog中记录了varchar(128(bytes))随后\(或许是发现了 slave 的SQL线程中断后\)又在 sql_log_binoff 下把 business_id 改回了 utf8mb3使表的结构在主从两端重新看起来一致了。---## 四、实验验证大胆的假设有了现在需要小心求证。## 4\.1 实验设计1. 搭建异步复制环境在 master 建表 dynamic_yyy_log 并插入数据确认复制正常。2. master 在 sql_log_binoff 下把 business_id 改成 utf8mb4再插入一条数据观察 slave 是否中断及报错。3. 观察 slave 的 SHOW SLAVE STATUS 与 replication_applier_status_by_worker。## 4\.2 实验步骤**步骤 1建表并验证复制**SQLINSERT INTO dynamic_yyy_log(id,business_id,serial,time_created,time_modified)VALUES(1,11111,11111,NOW(),NOW());**步骤 2关键操作——关 binlog 改字符集插数据****关binlog改回字符集**SQL-- 将列business_id有utf8mb3改为utf8mb4SET sql_log_binoff;ALTER TABLE dynamic_yyy_log MODIFY COLUMN business_idvarchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 业务主键;SET sql_log_binon;-- 在utfmb4下执行insertINSERT INTO dynamic_yyy_log(id,business_id,serial,time_created,time_modified)VALUES(2,22222,22222,NOW(),NOW());-- 将列business_id有utf8mb4改为utf8mb3SET sql_log_binoff;ALTER TABLE dynamic_yyy_log MODIFY COLUMN business_idvarchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 业务主键;SET sql_log_binon;**步骤 3观察 slave**SQLGreatSQL SHOW SLAVE STATUS\G...Slave_IO_Running: YesSlave_SQL_Running: NoLast_Errno: 13146Last_Error: Coordinator stopped because there were error(s) in the worker(s).The most recent failure being: Worker 1 failed executing transaction0ecdbd10-21e1-11f1-ae16-00163e892deb:415 at master log binlog.000001, end_log_pos 190926334....再看 worker 明细SQLGreatSQL SELECT * FROM performance_schema.replication_applier_status_by_worker LIMIT 1\G;SERVICE_STATE: OFFLAST_ERROR_NUMBER: 13146LAST_ERROR_MESSAGE: Worker 1 failed executing transaction0ecdbd10-21e1-11f1-ae16-00163e892deb:415 at master log binlog.000001, end_log_pos 190926334;Column 1 of table testdb.dynamic_yyy_log cannot be convertedfrom type varchar(128(bytes)) to type varchar(96(bytes) utf8mb3)...报错与现场问题完全一致此时查询表的结构信息列business\_id都是utf8mb3。 问题发生的假设得到验证。## 五、延伸问题## 5\.1 binlog 里记录了列的类型、长度、字符集吗mysqlbinlog -v解析事务 0ecdbd10\-21e1\-11f1\-ae16\-00163e892deb:415 的 binlog关键片段如下Plaintext### INSERT INTO testdb.dynamic_yyy_log### SET### 12 /* LONGINT meta0 */### 222222 /* VARSTRING(128) meta128 nullable0 */### 322222 /* VARSTRING(765) meta765 nullable0 */### 92026-03-18 09:43:37 /* DATETIME(0) */...结论很明确- **binlog 记录了列的类型与字节长度**。2 列即 business_id被记为 VARSTRING(128)128 正是该列在 utf8mb4 下的字节数。- **binlog 没有记录列的字符集**。binlog中只记录了列占多少字节并未记录列的字符集。## 5\.2 出了事怎么救既然根因是 slave 本地列长度和 binlog 不一致解法就是让 slave 对齐 master 写 binlog 时的状态——把 business_id 也改成 utf8mb4SQLSET sql_log_binoff;ALTER TABLE dynamic_yyy_log MODIFY COLUMN business_idvarchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 业务主键;SET sql_log_binon;改完后 START SLAVE这个事务可以继续回放。但主从字符集不一致主utf8mb3从utf8mb4那么什么时候还需要再改一次字符集## 5\.3 有没有容忍类型或长度变化的开关GreatSQL 提供了系统变量来控制主从之间的类型转换容忍度replica_type_conversions。- **默认值空字符串**禁止任何属性提升或降级主从对应列的长度和类型必须完全一致。本次问题中该变量正是空值所以一遇到 128 vs 96 就直接报错。- **ALL\_LOSSY** 允许会造成信息丢失的转换。- **ALL\_NON\_LOSSY** 允许不需要截断、无需特殊处理原始值的转换即目标类型的取值范围能覆盖源类型。- **ALL\_LOSSY,ALL\_NON\_LOSSY** 开启后所有支持的类型转换都允许无论是否有损。- **ALL\_SIGNED** 属性提升后的整数视为有符号类型默认行为。- **ALL\_UNSIGNED** 属性提升后的整数视为无符号类型。- **ALL\_SIGNED,ALL\_UNSIGNED** 优先将提升后的整数按有符号处理无法容纳时则按无符号处理。两个配置的书写顺序无影响。---## 结语这次中断的表象是表结构不一致真相却是结构一致、历史 binlog 不一致。字符集这种看似无害的字段属性一旦在 sql_log_binoff 下被悄悄改动DML操作就会在 binlog 里留下历史痕迹等 slave 回放时就可能跳出来叫停SQL线程。对于DBA的启示- 但凡涉及到“主从复制类型转换失败”情况的基本上都可以第一时间往字符集不一致方向去排查。- 日常巡检时对比主从两端数据列的长度、字符集、排序规则是否一致。- 不要在 sql_log_binoff 下改列定义列的字符集/长度变更要走正常 DDL 流程让变更进入 binlog保证主从同步演进。## 老叶有话说GreatSQL 社区现已上线“**AI助手**”功能我试着把这个问题丢给它互动结果如下。问 GreatSQL主从复制结构中从服务器上报告错误Column 1 of table zhgd_screen.dynamic_device_status_log cannot be converted from type varchar(128(bytes)) to type varchar(96(bytes) utf8mb3) 这种情况下一般是什么原因导致如何分析排查AI助手回答先说明一下我检索了官方手册**未查到针对这条报错文案的专项条目**下面基于 MySQL/GreatSQL 行复制ROW format的通用机制给您分析具体细节请以官方手册为准。## 一、这个报错的本质这是典型的 **RBR行复制列类型不匹配**错误对应 MySQL 错误码 1677 ER_SLAVE_CONVERSION_FAILED- 主库以 ROW 格式记录 binlog里面带有**主库表的列元数据**- 从库回放 TABLE_MAP / 行事件时会把主库列定义和**本地表的列定义**逐列比对只有可安全转换才放行- 报错说明第 1 列两边定义不一致无法转换。报错里的字节数很关键- 主库侧varchar(128(bytes)) —— 列最大容量 128 字节- 从库侧varchar(96(bytes) utf8mb3) —— 96 字节且字符集是 utf8mb3。一个很典型的对应关系是**主库 VARCHAR(32) utf8mb432×4128 bytes从库 VARCHAR(32) utf8mb332×396 bytes**——字符数相同但两边建表时的**默认字符集不同**导致表结构漂移了。GreatSQL 8.0 起默认字符集为 utf8mb4而 utf8 是 utf8mb3若从库是老版本迁移过来或建库时未显式指定字符集就很容易出现这种差异 GreatSQL 官方手册 - 字符集 校验集↗。## 二、常见成因按概率排序1. **两边默认字符集不一致时各自建表**主库 character_set_serverutf8mb4从库还是旧的 utf8mb3/latin1表不是通过复制建的而是各自初始化或分别导入的。2. **单边 DDL 导致结构漂移**- DBA 在从库上直接 ALTER 做验证主库没执行- 主库 ALTER 后从库执行失败被跳过检查是否配置了 replica_skip_errors / slave_skip_errors 跳过了 1xxx DDL 错误- 复制过滤规则Replicate_Do_DB / Replicate_Ignore_DB 等把这条 DDL 过滤掉了。3. **从库表被外部任务覆盖**备份恢复、数据导入脚本、初始化任务在从库上重建了这张表用的是不同 --default-character-set 的 dump。4. **历史架构调整**从库曾是别的主库的从库或做过切换后表结构没对齐。## 三、排查步骤**1. 看复制状态拿到出错时间线**sqlSHOW REPLICA STATUS\G-- 关注 Replica_SQL_Running、Last_SQL_Error、Last_SQL_Error_Timestamp-- 旧语法 SHOW SLAVE STATUS 也可用GreatSQL 新旧两套语法并行兼容GreatSQL 官方手册 - 恢复部分主从复制兼容接口↗**2. 两边对比表结构核心步骤**分别在主库和从库执行sqlSHOW CREATE TABLE zhgd_screen.dynamic_device_status_log\GSELECT COLUMN_NAME, ORDINAL_POSITION, COLUMN_TYPE,CHARACTER_SET_NAME, COLLATION_NAMEFROM information_schema.COLUMNSWHERE TABLE_SCHEMAzhgd_screenAND TABLE_NAMEdynamic_device_status_log;把两边结果逐列 diff重点看第 1 列的 COLUMN_TYPE 和 CHARACTER_SET_NAME。**3. 检查环境差异**sqlSHOW VARIABLES LIKE character_set_server;SHOW VARIABLES LIKE collation_server;SHOW VARIABLES LIKE binlog_format; -- 主库应为 ROWSHOW REPLICA STATUS; -- 看 Replicate_* 过滤规则SHOW VARIABLES LIKE %skip_errors%; -- 是否配置了跳错**4. 追溯 DDL 历史**用 mysqlbinlog 在主库 binlog 中搜该表名看这张表的 ALTER/CREATE 记录是否都到达了从库结合 Last_SQL_Error_Timestamp 缩小时间窗。**5. 数据层校验**结构对齐后建议用 pt-table-checksum 校验主从数据是否还有其他隐性差异。## 四、修复建议- **以主库为准修正从库结构**执行前先 STOP REPLICAsqlSTOP REPLICA;ALTER TABLE zhgd_screen.dynamic_device_status_logMODIFY 第1列列名 与主库完全一致的定义;START REPLICA;- ⚠️ 如果从库该列比主库**窄**且已有存量数据MODIFY 时可能因数据超出长度/字符集表示不了而失败这种情况下更稳妥的做法是在从库重建表CREATE TABLE ... LIKE 主库表结构再回填数据。- ❌ **不建议**用 replica_skip_errors1677 直接跳过——事件是跳过去了但主从数据从此不一致后患更大。只有在明确接受数据差异、紧急恢复复制时才考虑跳过单个事件。- **预防**两边统一 character_set_server/collation_server建库建表显式写 CHARACTER SET utf8mb4DDL 统一走变更流程、严禁在从库单边执行定期用 pt-table-checksum 巡检。如果您把主库和从库两边 SHOW CREATE TABLE 的结果贴出来我可以帮您精确定位是哪一列、哪种差异导致的。也可以到技术论坛发帖讨论[技术论坛](https://greatsql.cn/forum.php)

相关新闻

Intel SGX核心原理与开发入门:Enclave和硬件内存加密解析

Intel SGX核心原理与开发入门:Enclave和硬件内存加密解析

1. 引言:从一个被“偷看”的内存说起先从一个最直观的场景说起。假设你在云服务器上跑一个处理用户敏感数据的程序,比如医疗影像分析、金融风控模型,或者干脆就是一个简单的密码校验服务。这台服务器的操作系统是Linux,你有完整的…

2026/10/14 16:02:07 阅读更多 →
VS连接PostgreSQL全攻略:驱动选择、连接字符串与常见坑排查

VS连接PostgreSQL全攻略:驱动选择、连接字符串与常见坑排查

说实话,这个问题我在实际项目里见过太多次了。数据库换成了 PostgreSQL,后台开发还是 Visual Studio,结果新建连接向导里根本没有 PostgreSQL 的选项,只能手动写连接字符串,然后就是各种报错。尤其 VS2012 这种老版本&…

2026/10/14 16:02:07 阅读更多 →
插件系统加载激活机制详解:从报错 did not activate 到工程实践

插件系统加载激活机制详解:从报错 did not activate 到工程实践

开发工具用多了,早晚会遇到这么一行黑底白字的报错:failed to load plugins web boot: 2 entries did not activate我第一次看到它也懵了很久,以为是自己把环境变量搞坏了,后来才发现,问题出在我对“插件”这套机制的底…

2026/10/14 16:02:07 阅读更多 →

最新新闻

AI Agent状态清理:超时重试背后的系统性风险与四维治理

AI Agent状态清理:超时重试背后的系统性风险与四维治理

1. 这不是超时和重试的问题,是状态管理的系统性溃败“给 AI Agent 加超时和重试后,我才发现真正的坑在状态清理”——这句话刚在内部技术群刷出来时,我正盯着一个跑了37分钟、卡在waiting_for_tool_execution状态、内存占用飙升到4.2GB却毫无…

2026/10/14 16:41:53 阅读更多 →
嵌入式Qt记事本开发全链路:从交叉编译到中文文件IO

嵌入式Qt记事本开发全链路:从交叉编译到中文文件IO

简介:这是一份基于Qt6开发的跨平台记事本项目源码,面向嵌入式与桌面应用开发初学者及Qt进阶学习者,聚焦GUI界面构建、文件编码处理与轻量级文本编辑功能实现。项目完整呈现了现代C在Qt框架下的典型工程实践,涵盖主窗口&#xff08…

2026/10/14 16:41:53 阅读更多 →
计算机系统概论第一章答案精讲:ISA、微架构与算法性质

计算机系统概论第一章答案精讲:ISA、微架构与算法性质

简介:计算机系统概论(原书第二版)第一章习题答案以PDF形式提供,面向计算机专业学生、考研读者和自学入门者,用于对照教材习题检验对计算机系统基础概念的掌握。内容选自原书附录的精选解答,覆盖冯诺依曼通用…

2026/10/14 16:41:53 阅读更多 →
远视储备与近视防控:从原理到实操的家长指南

远视储备与近视防控:从原理到实操的家长指南

1. 远视储备不是“储备”,而是一笔会不断消耗的视力存款1. 远视储备不是“储备”,而是一笔会不断消耗的视力存款1.1 远视储备到底是什么很多家长第一次听到“远视储备”这个词,是在幼儿园体检或者眼科门诊的报告单上。医生指着上面的数字说&a…

2026/10/14 16:41:53 阅读更多 →
Python数据挖掘实战:K均值聚类从原理到应用

Python数据挖掘实战:K均值聚类从原理到应用

1. 从一个真实需求说起:为什么K均值聚类值得你花时间搞懂做数据挖掘这些年,我越来越觉得,K均值聚类是那种“看起来简单、用起来真香、但踩坑也真不少”的算法。很多刚入门的朋友一听到“无监督学习”四个字就头大,觉得没有标签怎么…

2026/10/14 16:41:53 阅读更多 →
MinGW-w64离线安装包:断网Windows下C/C++工具链部署指南

MinGW-w64离线安装包:断网Windows下C/C++工具链部署指南

简介:MinGW-w64是为64位Windows系统打造的GCC工具链离线安装包,面向需要在Windows环境下学习或开展C语言开发的程序员。压缩包约2000个文件、133.98MB,主要由h头文件、Python脚本、a静态库、pyc编译文件、exe可执行程序、dll动态库及少量c源文…

2026/10/14 16:40:52 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →