3. 变更前检查清单的制定与验证
为什么数据库 schema 变更需要专门的检查清单
数据库 schema 变更与普通代码发布有本质区别:它直接触碰持久化数据,一旦执行往往不可逆,且影响面横跨应用层、数据层和运维层。一次看似简单的“加字段”可能因为锁表导致写入阻塞,一次“改类型”可能让旧版本应用读取失败。因此,变更前检查清单不是形式主义,而是把散落在 DBA、后端、运维脑中的隐性约束固化为可逐条核对的显性条目。
本案例以一次真实场景为例:为订单库 orders 表新增 channel_code 字段并建立索引,用于区分下单渠道。我们将制定一份覆盖备份、依赖、容量、兼容性四个维度的检查清单,并通过模拟执行验证其完整性。
检查清单的四个维度与关键条目
清单条目必须可验证、可判定,避免“确认无误”这类无法执行的描述。每个条目应包含:检查对象、判定标准、执行方式、不通过时的处置。
| 维度 | 检查条目 | 判定标准 | 执行方式 |
|---|---|---|---|
| 备份 | 变更前全量备份是否完成 | 备份文件存在且校验和匹配 | 检查备份任务日志与 md5 |
| 备份 | binlog 位点是否记录 | 已记录当前 master 位点 | SHOW MASTER STATUS |
| 依赖 | 应用是否使用 SELECT * | 无 SELECT * 查询该表 | 代码扫描 + 慢查询日志 |
| 依赖 | 下游数据同步任务是否感知新字段 | 同步任务 schema 已更新或忽略新字段 | 检查 ETL 配置 |
| 容量 | 磁盘剩余空间是否足够 | 剩余空间 > 表大小 × 2 | df -h + 表大小查询 |
| 容量 | 索引新增后预估大小 | 预估增量 < 剩余空间 30% | 按行数 × 索引宽度估算 |
| 兼容性 | 旧版本应用能否容忍新字段 | 旧版本读取不报错 | 在预发环境用旧版本验证 |
| 兼容性 | 字段默认值是否影响存量数据 | 默认值语义正确且不阻塞写入 | 检查 DDL 语句 |
检查清单的依赖关系与执行顺序
清单条目并非彼此独立。备份必须在任何写操作前完成;容量检查依赖表大小统计,而表大小统计又依赖统计信息是否新鲜;兼容性验证需要在预发环境完成,不能在生产变更窗口内临时验证。下图展示了各条目之间的前置依赖与执行流向。
模拟执行:验证清单的完整性与可操作性
清单制定完成后,不能直接用于生产。需要在预发环境用相同表结构、相近数据量进行一次模拟执行,重点验证三件事:条目是否遗漏、判定标准是否可操作、执行顺序是否合理。
模拟执行的具体做法:
- 在预发库创建与生产
orders表结构一致的副本,灌入约 500 万行模拟数据。 - 按清单顺序逐条执行,记录每条的实际耗时、输出结果和是否触发阻断。
- 对每条“通过”的条目,确认判定标准是否明确——例如“磁盘剩余 > 表大小 × 2”需要实际查询表大小和磁盘空间,而不是凭经验判断。
- 对每条“不通过”的条目,验证处置动作是否可执行——例如备份校验失败时,是否有重新备份的流程和时间预算。
模拟执行中发现的两个典型问题:
- 原清单缺少“统计信息是否新鲜”条目。预发环境因统计信息过期,表大小查询结果偏差 40%,导致容量判断失真。补充条目:变更前执行
ANALYZE TABLE orders并确认统计时间在 24 小时内。 - 原清单将“旧版本应用读取验证”放在生产变更窗口内执行,模拟发现该验证需要 15 分钟以上,且需要部署旧版本实例,不适合在窗口内完成。调整为变更前 1 天在预发环境完成。
最终检查清单(可直接使用)
| 序号 | 检查项 | 判定标准 | 执行命令/方式 | 不通过处置 |
|---|---|---|---|---|
| 1 | 全量备份完成 | 备份文件存在,md5 与记录一致 | 检查备份日志 + md5sum | 重新备份,推迟变更 |
| 2 | binlog 位点记录 | 已记录 file 和 position | SHOW MASTER STATUS | 立即记录,否则无法回滚 |
| 3 | 统计信息新鲜 | 统计时间在 24 小时内 | ANALYZE TABLE orders | 执行 ANALYZE 后重新检查 |
| 4 | 磁盘空间充足 | 剩余空间 > 表大小 × 2 | df -h + information_schema.TABLES | 清理空间或扩容 |
| 5 | 索引增量可控 | 预估索引大小 < 剩余空间 30% | 行数 × 索引宽度估算 | 评估是否必须建索引 |
| 6 | 无 SELECT * 查询 | 代码扫描无命中 | 静态扫描 + 慢查询日志 | 修改查询或确认兼容 |
| 7 | 下游 ETL 已适配 | 同步任务 schema 已更新 | 检查 ETL 配置 | 更新配置后重新验证 |
| 8 | 旧版本应用兼容 | 预发环境旧版本读取不报错 | 部署旧版本实例验证 | 调整字段默认值或推迟 |
| 9 | 默认值语义正确 | 默认值符合业务预期 | 检查 DDL 语句 | 修改 DDL 后重新评审 |
| 10 | 回滚方案就绪 | 回滚 DDL 已准备并验证 | 预发执行回滚测试 | 补充回滚方案 |
清单的验证不是一次性的。每次变更后应回顾:是否有条目未覆盖到实际发生的问题?判定标准是否过于宽松或严格?将新发现补充进清单,下一轮变更前重新模拟执行。清单本身也需要版本管理,与变更记录关联。