Cloudflare D1
Migrations
Schema
Deploy
SQLite

D1 中的迁移:如何对模式进行版本控制以及出错时会发生什么

D1 的迁移系统简单且运行良好 — 直到您需要恢复已在生产中运行的迁移并发现没有本机回滚。

D1 中的迁移:如何对模式进行版本控制以及出错时会发生什么

D1 的迁移系统是为了简单性而不是安全性而设计的。文件0 按顺序编号,通过1 应用,无回滚。与 Flyway、Liquibase 甚至 Rails 迁移系统等工具(允许向下迁移和双向版本控制)相比,D1 提供了一种单向流程。当迁移经过充分测试并且完全按计划进行时,这种方法会很有效。如果没有,恢复选项是有限的,需要在问题发生之前而不是期间做好准备。

D1 的迁移系统如何运作

2在项目目录4中创建编号为3的文件。该数字是连续的并决定应用顺序 - 5、6 等等。 wrangler 跟踪数据库本身内名为 7 的内部表中已经应用了哪些迁移。

8 按顺序应用所有待处理的迁移。 9 显示当前状态 - 已应用和待处理。这个流程对于大多数情况来说已经足够了。

结构限制:没有10。针对 D1 数据库应用的迁移没有自动撤消功能。如果迁移 11 在架构中引入了错误并且您需要恢复,则有两种选择。第一种是编写迁移 12,手动撤消 13 所做的操作 - 对于添加列等非破坏性操作是可能的,但对于删除数据的操作(例如 14 或 15)是不可能的。第二种是使用 D1 的 Time Travel 将数据库恢复到迁移前的某个点,适用于具有 30 天窗口的付费计划。

边缘的模式一致性问题

D1 复制会带来传统银行所没有的部署风险:迁移可能在主数据库上进行,而副本仍然加载旧架构。从过时的副本中读取数据的工作线程将针对与预期不同的模式执行查询。

具体场景:将列 16 添加到表 17 中,并进行迁移 18。迁移在主数据库上运行。同时,您部署更新后的 Worker,使 19。即使部署顺利并且主数据库已经具有正确的架构,命中尚未收到迁移的副本的请求也会失败并出现未知列错误。

传播间隔可达60秒。解决方案是将迁移的部署与代码的部署分开。正确的流程:应用迁移,显式等待至少 60 秒,然后部署新版本的 Worker。这种等待需要构建到 CI/CD 管道中 - 20° 没有“等待模式传播”标志,因此您需要手动构建此延迟。对于绝大多数情况,两个管道步骤之间的 21 就足够了。

生产环境中安全迁移的手册

在将任何迁移应用到生产数据库之前,导出完整的转储:22。该文件是您的手动恢复路径,以防出现问题并且时间旅行不可用或不充分。

使用与生产同等量的数据在临时数据库上测试迁移。对于具有 1,000 行的表,在 50 毫秒内运行的迁移对于具有 500 万行的表可能需要 20 秒 - 在这 20 秒内,数据库可能无法用于依赖于正在更改的表的查询。 D1 不像 PostgreSQL 那样具有 23 的后台重新索引功能。

对于需要零停机时间的架构更改,请使用分阶段部署模式。要重命名列,请按独立步骤处理该过程:首先,将新列添加为可为空;其次,部署您在两列(旧列和新列)中编写的代码;第三,回填作业,将现有记录中的数据从旧列复制到新列;第四,更新代码以仅从新列读取;第五,在后续迁移中删除旧列。将所有这些步骤组合到单个迁移中会产生不一致的窗口,并且不允许部分回滚。

在投入生产之前在本地测试迁移

24 在25 中创建一个真正的SQLite 文件。您可以使用 26 对该文件应用迁移,直接使用 27 客户端检查它,然后针对查询运行 28 以在部署之前验证索引是否正确使用。

本地和远程之间的差距就是复制。本地环境是一个纯 SQLite 实例,没有主层和副本 - 最终一致性问题不会在本地测试中出现。为了弥补这一差距,请在您的 Cloudflare 账户中创建一个单独的 D1 临时银行,首先在其中应用迁移,并使用近似生产量的数据验证行为。

当其他一切都失败时,时间旅行是B计划。 29 在付费计划的 30 天窗口内将银行恢复到当时的状态。这将恢复因破坏性迁移而删除的数据,并恢复无法通过正向迁移撤消的架构更改。该操作会替换整个数据库的状态 - 没有特定表的选择性恢复。如果迁移损坏了一个表,但其他表在该时间间隔内活动正常,则恢复也会将这些其他表恢复到之前的状态。

另请阅读

  • [Cloudflare D1:边缘的 SQLite 数据库 — 以及为什么“边缘”的含义并不像看上去的那样30
  • [生产中的 D1:性能、限制以及无法单独扩展的因素31
  • 【D1查询慢:如何诊断和优化32
  • [Workers 和 Pages:部署、路由以及每个模型隐藏的内容33
  • [现代 GraphQL API:模式设计、性能和有效模式34
  • [Cloudflare 负载均衡和地理转向:当 DNS 成为智能流量层35