一次普通的 DDL 变更——给一张表加一个字段。DBA 在 16 个分片上依次执行 ALTER TABLE,前 15 个顺利通过,第 16 个因为超时报错。来不及在维护窗口内重试,只好先上线再说。
结果就是:16 个分片中,15 个有新字段,1 个没有。
表结构不一致是怎么来的?
DDL 在多个分片上执行时间不同。 同一条 ALTER TABLE 在不同分片上的执行时间可能相差很大,某个分片执行异常就会导致遗漏。
中间件版本升级遗漏。 中间件本身维护着一份表结构元数据,DDL 变更后需要同步更新,如果被遗漏,SQL 路由和解析就会出错。
人工操作失误。 漏执行某个分片、执行了错误的 SQL——这些都是现实发生过的案例。
灰度发布期间新旧结构并存。 新版本应用读写新结构,旧版本读写旧结构,灰度时间过长或回滚不彻底也可能导致不一致。
后果有多严重?
应用层 SQL 解析错误、数据写入失败、查询结果异常、中间件路由错乱——这些后果的严重程度取决于具体场景,但一个索引或约束的不一致可能导致查询性能骤降或数据完整性问题。
预防:把问题挡在发生之前
建立 DDL 变更管理平台。 将所有 DDL 变更纳入统一流程,自动在每个分片上执行并记录结果,任何分片执行失败自动告警。
使用自动化执行脚本。 包含前置检查(确认所有分片当前表结构一致)、执行阶段(逐分片执行并记录结果)、后置校验(确认新表结构一致)三个环节。
变更前的结构与数据校验。 先对比所有分片的当前表结构是否一致,不一致则先修复再变更。
同步更新中间件元数据。 把中间件元数据更新纳入变更流程的一部分。
检测:及时发现异常
定时对比各分片表结构。 自动对比所有分片的字段名、类型、默认值、索引、约束等。
元数据一致性巡检。 定期检查中间件元数据与数据库实际结构是否一致。
修复:出了问题怎么处理
先评估影响范围,再分级修复。 按分片逐一执行缺失的 DDL,处理异常数据,提前准备好回滚方案。
根本解法:从源头消除问题
分布式数据库中,一张逻辑表在底层自动分布到多个节点,但 DDL 变更只需要执行一次,数据库内部自动将变更同步到所有相关节点。TiDB 和平凯数据库(TiDB 企业版)就是这样的分布式数据库——DDL 语句执行一次即可生效到所有节点,即使是加索引等重操作,TiDB 也支持在线并发执行,不会锁表影响业务。对于正在为分库分表环境下的表结构不一致问题头疼的团队来说,从源头消除这个问题的方向值得认真考虑。