十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

增量同步中的DDL变更处理策略——持续迁移期间的结构变更、同步稳定性与演练实战

增量同步中的DDL变更处理策略——持续迁移期间的结构变更、同步稳定性与演练实战 文章目录每日一句正能量1. 背景与问题持续迁移最怕的不是DML积压而是一次未经控制的DDL2. 环境与数据先确认KFS版本、同步组合和DDL策略2.1 第一步不是写ALTER而是确认同步组合2.2 DDL同步和普通DML过滤不是同一个机制2.3 默认策略建议DDL不是“全开”而是白名单2.4 为每个DDL记录“结构版本”3. 复现过程六类DDL风险完全不同3.1 ADD nullable column最适合做兼容扩展3.2 ADD NOT NULL无默认值看似简单实际很危险3.3 RENAME COLUMN旧事件与旧应用会立即失效3.4 DROP COLUMN属于高风险收缩型DDL3.5 类型变更必须区分扩宽和收窄3.6 主键变更通常直接进入专项方案4. 方案实施生产环境采用“Expand-Contract DDL白名单 发布状态机”4.1 第一条规则兼容性扩展优先“目标先行”4.2 第二条规则自动同步DDL必须走白名单4.3 第三条规则DDL配置变更本身也要受控4.4 第四条规则新增字段必须同时支持旧应用和新应用4.5 第五条规则DDL前先看增量积压4.6 第六条规则DDL前检查长事务4.7 第七条规则索引变更和列变更分开考虑4.8 第八条规则DDL和DML混合事务要专项验证4.9 第九条规则所有DDL必须先跑“旧DML 新DML回放”旧事件新事件4.10 第十条规则生产DDL必须有预检查SQL5. 结果对比一次ADD COLUMN演练应该记录什么5.1 演练 D01ADD nullable column5.2 演练 D02ADD NOT NULL5.3 演练 D03DROP COLUMN5.4 演练 D04CREATE INDEX5.5 演练 D05目标DDL执行失败5.6 官方提供单表刷新能力但不应把它当第一选择5.7 演练结果表6. 风险与复盘DDL处理的最终目标不是“不断同步”而是“结构版本始终可解释”6.1 风险一全自动DDL看起来省事实则放大爆炸半径6.2 风险二跳过DDL事务后盲目继续同步6.3 风险三只考虑数据库不考虑应用版本6.4 风险四DROP操作破坏回退6.5 风险五目标先行不是万能方法6.6 风险六索引DDL造成同步延迟爆发6.7 风险七没有结构版本审计回退方案先恢复“结构可应用性”再恢复数据如果已经产生数据差异DDL回退门禁最终复盘附录 AddlSupport白名单示例附录 BExpand-Contract附录 C最低DDL演练用例附录 D最低发布门禁每日一句正能量当我们的内心足够笃定外界的风声便只是背景音。笃定不是听不见而是听见后依然能专注自己的节奏。它源于清晰的自我认知知道自己是谁要去哪里相信什么。当内心有了稳固的坐标系外界的褒贬就只是参照物而非判决书。主题结构变更与同步稳定性 / 持续迁移 / KFS 增量同步重点DDL 兼容评估、ddlSupport、变更白名单、Expand-Contract、旧/新 DML 兼容、演练记录、数据校验与回退适用场景已经进入全量完成 KFS 增量同步阶段但源系统仍需持续发版、增加字段、调整索引或修改表结构的长期迁移项目。1. 背景与问题持续迁移最怕的不是DML积压而是一次未经控制的DDL异构迁移周期短则几天长则几个月。如果系统已经进入全量迁移完成 KFS持续增量同步但距离正式割接还有六周业务不可能因为数据库迁移就停止发布。这六周内很可能发生ALTERTABLEtrade_orderADDpromo_codeVARCHAR(32);CREATEINDEXidx_order_promoONtrade_order(promo_code);ALTERTABLEcustomerMODIFYCOLUMNcustomer_nameVARCHAR(300);DROPCOLUMNlegacy_flag;在单数据库系统里这些只是普通发布。在持续增量迁移里每条 DDL 都会同时影响源端结构版本 日志解析 KFS事务解释 目标表结构 旧版本应用 新版本应用 历史全量数据 正在回放的旧事务因此它不是简单的“数据库改表”。它是一场跨两个数据库、两个结构版本以及一条增量复制链路的协议升级。最典型故障是源端先 ADD COLUMN ↓ 应用V2马上开始写新列 ↓ KFS抽取到带新列的DML ↓ 目标表还没有这个列 ↓ 目标应用失败 ↓ 同步进入ERROR/OFFLINE ↓ 增量开始积压更危险的情况源端DROP COLUMN但 KFS 队列里仍然存在几分钟前产生、还没应用到目标的旧事务这些事务仍引用旧列。这时即使目标也同步执行DROP COLUMN后面的旧事务反而可能无法落库。所以持续迁移中的第一原则是DDL 的安全性不能只按“DDL执行成功”判断而要按“变更前、变更中、变更后的 DML 是否都还能被正确回放”判断。2. 环境与数据先确认KFS版本、同步组合和DDL策略示例环境源端 MySQL 8.0 / SQL Server 2017 目标 KingbaseES V9 全量 已完成 增量 KFS ONLINE 核心表 trade_order 12亿行 customer 1.2亿行 日常发布 每周2~3次 迁移剩余周期 6周2.1 第一步不是写ALTER而是确认同步组合Kingbase FlySync 官方部署前评估文档明确要求确认源数据库真实版本 确认目标数据库版本 确认KFS支持的同步组合因为早期项目交流版本和生产实际版本可能不同。因此每次重大 DDL 变更记录至少绑定source_db_version target_db_version KFS_version compatibility_mode change_id不能写一个“KFS支持ALTER TABLE”就当作永久结论。2.2 DDL同步和普通DML过滤不是同一个机制KFS 管理手册明确说明replicate do/ignore主要用于 DML 过滤不能自动承担全部 DDL 过滤控制。KFS 为 DDL 提供ddlSupport过滤器。官方列出的 DDL 对象包括TABLE SCHEMA VIEW INDEX FUNCTION TRIGGER ...常见操作类型CREATE DROP ALTER TRUNCATE而且在异构数据源 DDL 同步场景中官方说明通常需要在源端配置 DDL 过滤。所以项目必须明确哪些DDL允许同步 哪些DDL必须过滤 哪些DDL只能人工执行目标版本2.3 默认策略建议DDL不是“全开”而是白名单测试环境可以{DEFAULT:Y}但生产持续迁移不建议默认放开所有 DDL。更稳妥ADD nullable column CREATE/DROP INDEX 部分安全ALTER允许。而DROP TABLE DROP COLUMN TRUNCATE 主键变更 复杂类型变更 触发器 函数默认阻断或人工审批。原因很简单DML失败通常影响若干事务错误 DDL 可能让后续所有事务都无法应用。2.4 为每个DDL记录“结构版本”建议变更台账change_id schema_version source_object source_ddl target_ddl ddl_class KFS_mode application_min_version application_max_version rollback_sql validation_case owner例如schema_version 2026.08.08.01这样排查增量错误时可以回答这个事务是在哪个结构版本产生的 目标当时是什么版本3. 复现过程六类DDL风险完全不同3.1 ADD nullable column最适合做兼容扩展源ALTERTABLEtrade_orderADDpromo_codeVARCHAR(32)NULL;旧应用INSERTINTOtrade_order(order_id,amount)VALUES(?,?);新应用INSERTINTOtrade_order(order_id,amount,promo_code)VALUES(?,?,?);只要promo_code允许NULL目标先建出这个列后旧DML 新DML都能工作。因此这是一类典型Backward Compatible DDL3.2 ADD NOT NULL无默认值看似简单实际很危险例如ALTERTABLEtrade_orderADDtenant_idBIGINTNOTNULL;历史12亿行tenant_id从哪里来旧应用INSERT时不提供tenant_id又怎么办所以这种变更至少要拆ADD nullable ↓ 回填历史 ↓ 应用开始写 ↓ 验证NULL0 ↓ 最后SET NOT NULL而不是一步完成。3.3 RENAME COLUMN旧事件与旧应用会立即失效原mobile改phone如果一步RENAMECOLUMNmobileTOphone;旧应用仍写mobile失败。KFS 积压队列里的旧事务也可能仍带mobile所以持续迁移期间推荐ADD phone 双写 mobile phone 回填 切读 退役旧应用 确认backlog0 最后DROP mobile即Expand → Migrate → Contract3.4 DROP COLUMN属于高风险收缩型DDL删除legacy_flag前要回答旧应用还写吗 KFS积压事务还引用吗 报表还查吗 回退版本还需要吗只有所有旧版本退出 KFS backlog0 回退窗口结束才适合 DROP。所以迁移阶段通常允许“加东西”谨慎“删东西”。3.5 类型变更必须区分扩宽和收窄VARCHAR(32) → VARCHAR(128)通常风险较低。但VARCHAR(128) → VARCHAR(32)必须先SELECTMAX(LENGTH(col));确认没有截断。数字BIGINT → INT更要检查范围。异构情况下还要考虑源类型语义 目标类型范围 字符长度是byte还是character 时间精度3.6 主键变更通常直接进入专项方案KFS 官方源端评估文档强调原则上待同步表应含主键没有主键时 UPDATE/DELETE 可能存在问题。所以如果迁移期间执行DROP PRIMARY KEY ADD PRIMARY KEY(...)这不仅是表结构变化而是改变复制定位行的身份模型应直接按L4/BLOCKER处理单独演练。4. 方案实施生产环境采用“Expand-Contract DDL白名单 发布状态机”4.1 第一条规则兼容性扩展优先“目标先行”对 ADD nullable columnT1 目标先ADD列 T2 确认目标旧DML仍正常 T3 源端ADD列 T4 KFS观察结构/事务 T5 发布应用V2这样在源端真正产生新列DML之前目标已经准备好。注意目标先行不是所有 DDL 都适用。它适用于向后兼容的扩展而不是删除/重命名/收窄4.2 第二条规则自动同步DDL必须走白名单示例{DEFAULT:N,TABLE:{APP.*:{CREATE:Y,ALTER:Y,DROP:N,TRUNCATE:N}}}思路允许受控TABLE ALTER 禁止生产自动DROP/TRUNCATEINDEX 可以根据项目放开。TRIGGER/FUNCTION 建议异构迁移中更加谨慎因为源端定义往往不能直接视为目标端语义等价4.3 第三条规则DDL配置变更本身也要受控KFS 官方管理手册说明修改flysync.ini setupCDC.conf等配置时需要先停止同步服务完成修改并更新配置后再启动。所以今天临时想放开某类DDL不能在生产随手改文件。应该纳入KFS配置变更窗口并记录停止时间 最后seqno 重新启动时间 积压增长 恢复耗时4.4 第四条规则新增字段必须同时支持旧应用和新应用安全发布顺序DDL Expand ↓ 应用兼容版本 ↓ 历史回填 ↓ 读路径切换 ↓ 观察 ↓ Contract不是DDL改名 应用发布同时赌两个操作零故障。4.5 第五条规则DDL前先看增量积压假设当前KFS lag20min现在做DROP COLUMN old_col队列里20分钟旧事务还可能引用old_col因此高风险 DDL 门禁应该要求latency threshold pending_tx threshold oldest_pending_tx threshold收缩型 DDL最好 backlog04.6 第六条规则DDL前检查长事务源端长事务BEGIN ... 运行30分钟期间做 DDL。它提交后增量日志可能带有DDL前结构对应的事务内容。因此割 DDL 时不只看KFS latency还看oldest active tx保证结构边界清晰。4.7 第七条规则索引变更和列变更分开考虑CREATEINDEX通常不改变行格式。但会影响锁 CPU IO WAL 同步延迟 目标写吞吐12亿行表在线建索引可能导致KFS apply速度下降因此索引 DDL 的验证重点不是列兼容而是同步稳定性和性能4.8 第八条规则DDL和DML混合事务要专项验证KFS 官方 KES 不停机迁移实施资料提到keepMixDML用于处理某些同时涉及 DDL 与 DML 的场景例如 create table as 类操作并可控制是否保留相关 DML。这提醒我们只验证纯 ALTER TABLE 还不够DDLDML混合操作必须单独进入演练用例。4.9 第九条规则所有DDL必须先跑“旧DML 新DML回放”演练环境不能只执行ALTERTABLE...然后成功就判 PASS。必须准备旧事件DDL之前生成INSERT old_columns UPDATE old_columns DELETE新事件DDL之后INSERT with new column UPDATE new column顺序先把目标置于正式迁移时可能存在的结构版本 →回放旧事件 →执行/同步DDL →回放新事件确认两边都成功。4.10 第十条规则生产DDL必须有预检查SQL加 UNIQUE 前SELECTkey,COUNT(*)FROMtGROUPBYkeyHAVINGCOUNT(*)1;加 NOT NULL 前SELECTCOUNT(*)FROMtWHEREcISNULL;类型收窄SELECTMAX(LENGTH(c));主键调整NULL 重复 KFS定位能力全部先确认。DDL失败不是最佳反馈方式。5. 结果对比一次ADD COLUMN演练应该记录什么下面给一份演练模板。5.1 演练 D01ADD nullable columnDDLALTERTABLEtrade_orderADDpromo_codeVARCHAR(32)NULL;顺序1. 目标先ADD 2. V1旧写请求1000条 3. 源端ADD 4. KFS持续ONLINE 5. V2新写promo_code 1000条 6. V1再写1000条 7. 比较源目标验证旧请求成功 新请求成功 KFS ERROR0 目标promo_code值一致 COUNT一致 关键Checksum一致结果PASS5.2 演练 D02ADD NOT NULL目标ADD tenant_id NOT NULL预检查发现历史NULL4.8亿结论NO-GO修改方案ADD NULL →批量回填 →新应用强制写 →NULL归零 →最后NOT NULL这就是演练的价值把生产故障提前变成评审结论5.3 演练 D03DROP COLUMN旧 KFS backlog3分钟其中仍有旧列更新。演练先DROP目标列结果旧事务应用失败结论DROP必须等待 旧应用下线 backlog0 回退窗口结束5.4 演练 D04CREATE INDEX12亿行表CREATEINDEXidx_xONtrade_order(x);记录DDL耗时 目标CPU 目标IO KFS apply TPS KFS latency 业务P95假设索引构建期间KFS latency 2s → 180s虽然 DDL 最终成功迁移稳定性仍判 FAIL应改低峰 更低并发 更适合的在线构建策略 分区级处理5.5 演练 D05目标DDL执行失败模拟源端ADD列成功 目标ADD失败KFS后续新列DML失败 ERROR:OFFLINE恢复冻结V2新字段写 记录seqno 目标补ADD列 确认结构 恢复KFS 等待积压清零 重做最近窗口校验恢复耗时例如95秒演练报告应该记录这个数。不是只写“已恢复”5.6 官方提供单表刷新能力但不应把它当第一选择KFS 官方管理手册提供reload-table单表刷新可把不一致表强制刷新为一致数据。它很有价值。但 DDL 故障后不能第一反应就是整张12亿行表reload更合理先修结构 ↓ 判断失败事务范围 ↓ 能重放则重放 ↓ 能范围修复则范围修复 ↓ 最后才考虑整表刷新5.7 演练结果表用例风险结果结论ADD NULL列L1PASS目标先行ADD NOT NULLL4BLOCKED分阶段实施DROP列L4BLOCKEDContract后置CREATE INDEXL2性能FAIL调整窗口类型收窄L4BLOCKED先治理数据目标DDL失败L3恢复95sRunbook有效文中的数值为演练模板示例不是生产实测。6. 风险与复盘DDL处理的最终目标不是“不断同步”而是“结构版本始终可解释”6.1 风险一全自动DDL看起来省事实则放大爆炸半径源端开发误执行DROPTABLE如果生产所有DDL自动同步目标也会立即受到影响。所以建议DEFAULTN 白名单而不是DEFAULTY6.2 风险二跳过DDL事务后盲目继续同步KFS 提供skip seqno等故障处理能力。但如果失败事务是ADD COLUMN直接跳过后结构仍未变化后面的新列 DML 仍会持续失败。所以跳过业务无关异常事务和跳过结构边界事务是两回事。关键 DDL 不应为了让状态变绿就直接 skip。6.3 风险三只考虑数据库不考虑应用版本DDL迁移真正存在三个版本源数据库schema 目标数据库schema 应用SQL schema expectation任何两边不匹配都会出错。所以变更审批必须包含最低兼容应用版本 旧应用退役时间6.4 风险四DROP操作破坏回退如果新版本上线当天DROP legacy_col后来应用需要回滚 V1V1还读legacy_col应用回滚也失败。所以数据库Contract必须晚于应用回退窗口6.5 风险五目标先行不是万能方法目标先 ADD安全目标先 DROP危险目标先修改收窄类型同样危险所以目标先行仅用于Backward-Compatible Expansion6.6 风险六索引DDL造成同步延迟爆发DDL没有报错不等于迁移链路健康必须同时关注apply TPS latency CPU IO lock wait6.7 风险七没有结构版本审计几周持续迁移后出现问题“这个列什么时候加的” “KFS当时是什么位置” “V2什么时候开始写”没人答得出来。所以每个 DDL 必须change_id schema_version timestamp KFS watermarks application_version全部关联。回退方案先恢复“结构可应用性”再恢复数据DDL故障的回退逻辑和普通 DML 不一样。第一目标不是马上把所有数据改回去而是先让目标结构重新能够接受正在排队的事务。典型流程1. 冻结后续DDL 2. 必要时冻结V2新字段写 3. 记录KFS seqno / source watermark 4. 判断失败DDL是否需要目标补执行或源端回滚 5. 恢复源目标兼容结构 6. 恢复增量应用 7. 等待backlog归零 8. 校验DDL窗口内的数据 9. 再决定是否继续新版发布如果已经产生数据差异优先级事务重放 主键/时间范围补偿 KFS单表刷新 重新全量越往下成本越高。DDL回退门禁KFS重新ONLINE pending_tx0 失败事务已解释 源/目标结构版本明确 DDL窗口COUNT一致 关键Checksum一致 新列/旧列业务值一致 应用V1/V2回归通过没有达到不允许继续下一条DDL最终复盘持续迁移期间的 DDL 管理推荐建立五层防线第一层兼容评估 确认版本、同步组合、DDL类型和目标语义 第二层DDL白名单 默认阻断高危DROP/TRUNCATE/主键变更 第三层Expand-Contract 先加兼容结构再迁数据/应用最后收缩 第四层演练 旧DML DDL 新DML 故障恢复全部演 第五层门禁和回退 结构、KFS状态、数据校验未闭合就不继续如果只记住一句话增量同步中的 DDL 不是一条 SQL而是一次“结构版本升级”安全标准不是它能执行而是升级前后所有仍可能到达的事务都能被正确解释和应用。持续迁移项目只要把这个原则建立起来业务团队就不需要在几周甚至几个月迁移期间完全冻结发版同时也不会因为一次普通ALTER TABLE把整条增量链路推入不可控状态。附录 AddlSupport白名单示例{DEFAULT:N,TABLE:{APP.*:{CREATE:Y,ALTER:Y,DROP:N,TRUNCATE:N}}}实际支持范围应按部署的 KFS 版本、源/目标数据库组合进行验证。附录 BExpand-ContractEXPAND 新增兼容列/表/索引 MIGRATE 双写、回填、切读、数据验证 CONTRACT 旧应用退出 KFS backlog归零 回退窗口结束 删除旧结构附录 C最低DDL演练用例[ ] ADD NULL列 [ ] ADD NOT NULL列 [ ] ADD带DEFAULT列 [ ] CREATE INDEX [ ] DROP INDEX [ ] RENAME列 [ ] 扩宽类型 [ ] 收窄类型 [ ] DROP列 [ ] 主键/唯一键变化 [ ] DDL执行失败 [ ] KFS中断恢复 [ ] DDL前旧事件回放 [ ] DDL后新事件回放 [ ] DDLDML混合场景附录 D最低发布门禁[ ] KFS ONLINE [ ] latency低于门限 [ ] error transaction0 [ ] 长事务低于门限 [ ] ddlSupport规则已确认 [ ] 目标DDL已在相同版本验证 [ ] V1旧应用仍兼容 [ ] V2新应用已验证 [ ] 数据基线已记录 [ ] 回退DDL已演练 [ ] replay兼容已验证转载自https://blog.csdn.net/u014727709/article/details/163780736欢迎 点赞✍评论⭐收藏欢迎指正
返回列表