LabHub
学习 学习路径 课程

SI 的数据库运维

编写 schema 变更与回滚脚本

在 LabHub 中继续学习

目标

使用扩展—迁移—收缩模式变更 schema,并建立一整套变更管理方案,包括回滚脚本、分批回填、验证脚本和操作手册。

为什么重要

‘有 down 脚本,所以很安全’是最常见的误解。 用于撤销 DROP COLUMN 的 down 脚本只能恢复列结构,无法找回列中的值。 可逆性不是代码自身的属性,而是代码、数据和时间三者共同作用的结果; 同一项变更若昨天刚部署,可能还可逆,但积累一百万条数据后就可能不可逆。 此外,若把大规模回填放在一个事务中执行,锁和日志量会急剧增加, 导致只读副本落后,查询服务向用户展示过期数据。 本实验将让你亲手练习如何避开这些陷阱。

步骤

  1. 准备:需要 dbo-schema 实验中的 /root/db/si.db。 如果不存在,可以使用 /opt/lab/fixtures/dbo/si-base.sql 创建。
  2. 将当前 schema 保存为 /root/db/schema_v1.sql, 并创建 /root/db/baseline.txt。文件包含三行:
    orders_cnt=<ORDERS 행 수>
    orders_amt=<ORDERS 의 ORD_AMT 합계>
    item_qty=<ORDER_ITEM 의 QTY 합계>
    
  3. 创建 /root/db/changelog.csv。首行为 chg_id,date,object,ddl_file,rollback_file,est_sec,approver。 预先登记第 3~5 步将要创建的 3 项变更。 ddl_filerollback_fileapprover 都不能为空, est_sec 必须填写数字。
  4. 创建 /root/db/mig/V2__add_dlvr_sts.sql
    • ORDERS 中添加 DLVR_STS_CD 列(默认值为 '01'
    • 将所有现有行填充为 '01' 应用后,DLVR_STS_CD 为 NULL 的行数必须为 0。
  5. 创建 /root/db/mig/V2__rollback.sql。 应用后,schema 必须与 schema_v1.sql 相同。 (请在 si.db 的副本上执行 up → down 进行确认。)
  6. 创建 /root/db/mig/V3__item_qty_check.sql。 将 ORDER_ITEM.QTY 的 CHECK 约束强化为不小于 1 且不大于 9999。 sqlite 不支持直接修改约束,因此必须执行表重建流程。 应用后,ORDER_ITEM 的行数和 QTY 总和仍须与第 1 步基线一致, 外键关系也必须保留。
  7. 创建 /root/db/batch-update.sh。脚本接收两个参数(DB파일 배치크기), 将 ORDERSDLVR_STS_CD'01' 的行改为 '02', 但要每次只处理指定的批量大小并循环执行。 最后一行输出 batches=<반복횟수> updated=<총건수>。 (为避免污染原始数据库,只能修改通过参数传入的 DB。)
  8. 创建 /root/db/mig-verify.sh。脚本接收两个参数(기준선파일 DB파일), 将基线中的三项指标与当前 DB 进行比较。 若全部一致,第一行输出 OK;若不一致,则输出以 NG 开头的行, 并指出哪些指标不同。两种情况的退出码分别为 0 和非 0。
  9. 编写 /root/db/mig-runbook.md。 必须包含 ## 작업 개요## 사전 백업## 적용 절차## 검증## 롤백 기준## 롤백 절차 六个 h2 标题。 正文中必须包含备份文件路径,以及用数字表示的回滚标准(耗时或验证失败数量)。

参考

Schema 快照与基线

将当前 schema 保存为 /root/db/schema_v1.sql, 并创建 /root/db/baseline.txt。文件包含三行:

orders_cnt=<ORDERS 행 수>
orders_amt=<ORDERS 의 ORD_AMT 합계>
item_qty=<ORDER_ITEM 의 QTY 합계>

等工作完成后才问‘原来有多少条?’就已经太晚了。请同时保留 schema 和数据指标。

变更管理台账

创建 /root/db/changelog.csv。首行为 chg_id,date,object,ddl_file,rollback_file,est_sec,approver。 预先登记第 3~5 步将要创建的 3 项变更。 ddl_filerollback_fileapprover 都不能为空, est_sec 必须填写数字。

将回滚脚本路径设为必填项,可以让你在填写台账时、而不是部署后,发现‘这项变更无法回滚’。

扩展脚本

创建 /root/db/mig/V2__add_dlvr_sts.sql

先添加列,再填充现有行。请思考先以允许 NULL 的方式添加并回填,与一开始就添加为 NOT NULL 有何区别。

回滚脚本

创建 /root/db/mig/V2__rollback.sql。 应用后,schema 必须与 schema_v1.sql 相同。 (请在 si.db 的副本上执行 up → down 进行确认。)

必须能够确认回滚后的 schema 与原始 schema 相同。比较快照是最可靠的方法。

表重建迁移

创建 /root/db/mig/V3__item_qty_check.sql。 将 ORDER_ITEM.QTY 的 CHECK 约束强化为不小于 1 且不大于 9999。 sqlite 不支持直接修改约束,因此必须执行表重建流程。 应用后,ORDER_ITEM 的行数和 QTY 总和仍须与第 1 步基线一致, 外键关系也必须保留。

修改约束需要创建新表并迁移数据。若不遵守正确顺序,数据或引用关系会损坏。

分批回填

创建 /root/db/batch-update.sh。脚本接收两个参数(DB파일 배치크기), 将 ORDERSDLVR_STS_CD'01' 的行改为 '02', 但要每次只处理指定的批量大小并循环执行。 最后一行输出 batches=<반복횟수> updated=<총건수>。 (为避免污染原始数据库,只能修改通过参数传入的 DB。)

在一个事务中执行大规模 UPDATE 会使锁和日志量急剧增加。请设计成反复执行,直到受影响行数变为 0。

迁移验证脚本

创建 /root/db/mig-verify.sh。脚本接收两个参数(기준선파일 DB파일), 将基线中的三项指标与当前 DB 进行比较。 若全部一致,第一行输出 OK;若不一致,则输出以 NG 开头的行, 并指出哪些指标不同。两种情况的退出码分别为 0 和非 0。

只看行数和总和,无法发现‘一条缺失、另一条翻倍’的情况。请使用多个指标。

操作手册

编写 /root/db/mig-runbook.md。 必须包含 ## 작업 개요## 사전 백업## 적용 절차## 검증## 롤백 기준## 롤백 절차 六个 h2 标题。 正文中必须包含备份文件路径,以及用数字表示的回滚标准(耗时或验证失败数量)。

这是需要在凌晨阅读的文档。命令应能够直接复制执行,并且必须用数字写清何时停止和回滚。