ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

SpacetimeDB 自动迁移(Automatic Migrations)完整指南:安全规则、破坏性变更与迁移策略

SpacetimeDB 自动迁移(Automatic Migrations)完整指南:安全规则、破坏性变更与迁移策略 SpacetimeDB 自动迁移Automatic Migrations完整指南安全规则、破坏性变更与迁移策略【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB导读本文以 SpacetimeDB 1.12.0 版官方文档为核心系统讲解当使用spacetime publish向已有数据库重新发布模块时SpacetimeDB 如何自动迁移数据库 schema 以匹配新模块定义。你将掌握哪些变更可安全自动执行、哪些会破坏旧客户端、哪些会被直接拒绝以及--delete-data、--break-clients等 CLI 参数的正确用法并结合仓库源码crates/schema/src/auto_migrate.rs、crates/cli/src/subcommands/publish.rs与冒烟测试理解底层迁移计划migration plan机制。什么是 SpacetimeDB 自动迁移在 SpacetimeDB 中数据库的 schema 指模块代码中声明的表tables、reducer、过程procedures、视图views以及它们所依赖的类型的集合。当你对已有数据库执行spacetime publish {database-name}SpacetimeDB 会比较旧模块定义与新模块定义并尝试自动迁移数据库 schema以匹配新模块。这意味着你可以更新模块代码并重新部署而只要变更在兼容范围内就不会丢失已有数据。从源码实现看这一过程由 crates/schema/src/auto_migrate.rs 中的ponder_migrate计算迁移计划MigratePlan其具体流程是CLI 先调用服务端pre_publish接口进行预检见 crates/cli/src/subcommands/publish.rs服务端比对新旧模块定义生成迁移计划并返回给 CLICLI 将迁移计划打印给用户若涉及破坏性变更则提示确认用户确认后CLI 携带迁移令牌MigrationToken与策略BreakClients正式提交 publish服务端执行计划中的各步AutoMigrateStep。✅ 安全变更Always Allowed以下变更始终被允许且不会破坏现有客户端新增表Adding new tables——未更新的客户端无法看到这些新表。新增索引Adding indexes。添加或移除Auto Inc注解Adding or removingAuto Incannotations。将表从 private 改为 public。新增 reducerAdding new reducers。移除Unique约束RemovingUniqueconstraints。这些安全操作在迁移计划中对应AddTable、AddIndex、AddSequence、AddConstraint、ChangeAccess等AutoMigrateStep变体见 crates/schema/src/auto_migrate.rs。其中AddTable会连同表的索引、约束、序列一并添加迁移计划中不会为它们单独生成步骤。⚠️ 潜在破坏性变更Potentially Breaking Changes以下变更自动迁移允许执行但可能对尚未更新的客户端造成运行时错误在表末尾新增带默认值的列。新列必须添加在表定义末尾且必须指定默认值。未更新的客户端不会感知到新列的存在。修改或移除 reducer。客户端若调用旧版本或已移除的 reducer将收到运行时错误。将表从 public 改为 private。订阅了该表的客户端会收到运行时错误。移除Primary Key注解。未更新的客户端仍会用旧主键作为本地缓存的唯一键收到更新时可能出现非确定性行为。移除索引。仅在特定场景下破坏性主要问题出现在涉及**半连接semijoin**的订阅查询中例如SELECT Employee.* FROM Employee JOIN Dept ON Employee.DeptName Dept.DeptName出于性能考虑SpacetimeDB 仅当两个连接列Employee.DeptName和Dept.DeptName上都建有索引时才允许此类订阅查询。移除任一索引都会使该订阅失效导致客户端运行时错误。从源码层面看潜在破坏性由迁移计划的breaks_client()判定只要计划中包含DisconnectAllUsers步骤即视为会破坏客户端见 crates/schema/src/auto_migrate.rs。例如AddColumns是一种破坏布局兼容性的操作必须先执行DisconnectAllUsers断开所有用户才能安全完成该步骤要求新增列位于表末尾且连续并且必须带默认值见 crates/schema/src/auto_migrate.rs。破坏性变更的发布确认当迁移计划判定存在破坏性变更时CLI 会提示确认。对应参数详见 crates/cli/src/subcommands/publish.rs# 跳过此变更会破坏现有客户端的确认提示 spacetime publish my-db --break-clients # 等价写法通过 --yes 明确选择跳过该类提示 spacetime publish my-db --yesbreak-clients # --yes 支持多个值逗号分隔或重复传入均可 spacetime publish my-db --yesmigrate,break-clients--yes的可用值定义于 crates/cli/src/subcommands/publish.rs包括all等价于全部跳过、remote跳过发布到非本地服务器的确认、migrate跳过迁移确认如主版本升级、break-clients、skip-login、delete-data。注意--yes的值必须用连接如--yes my-db会把my-db当作数据库名。❌ 禁止变更Forbidden Changes以下变更无法通过自动迁移完成会导致 publish 失败移除表Removing tables。移除或修改已有列包括修改类型、重命名、重排列。添加无默认值的列。新列必须有默认值以便为已有行填充数据。在表中间添加列。新列必须添加在表定义末尾。改变表是否用于scheduling。添加Unique或Primary Key约束。这可能使已有表处于非法状态。这些拒绝逻辑在源码中体现为一组AutoMigrateError错误消息例如见 crates/schema/src/auto_migrate.rsRemoving a column {column} from table {table} requires a manual migration Reordering table {table} requires a manual migration Changing the type of column ... requires a manual migration Adding a unique constraint {constraint} requires a manual migration Changing the table type of table ... requires a manual migration Changing the event flag of table {table} requires a manual migration当你实际尝试类似操作时CLI 会输出类似下面的错误Error: Database update rejected: Errors occurred: Adding a column alliance to table character requires a manual migration值得注意的是源码中注释指出移除表不再被视为错误见 crates/schema/src/auto_migrate.rs 的测试注释仓库还提供了auto-migration-drop-event-table-before/after等冒烟测试模块。但在本文所依据的 1.12.0 文档语义中移除表仍属于禁止变更实际操作时请以你部署的服务端版本实际行为为准并在发布前通过 pre-publish 输出仔细核对迁移计划。底层原理迁移计划与迁移策略自动迁移并非无脑执行而是遵循一套严谨的计划 策略 令牌机制理解它有助于你预判发布结果。迁移计划MigratePlanMigratePlan分为两类crates/schema/src/auto_migrate.rsAutoMigratePlan由一系列有序步骤组成。步骤排序有严格约束——同一对象的Remove类步骤必须排在Add类步骤之前见 crates/schema/src/auto_migrate.rs否则会出现先重新添加旧索引、再删除索引导致目标索引根本没建出来的错误。ManualMigratePlan需要手动迁移的变更要求新模块带有Lifecycle::Updatereducer 支持。迁移策略与令牌MigrationPolicy MigrationToken服务端通过MigrationPolicy判定发布是否被允许crates/schema/src/auto_migrate.rsCompatible只允许不破坏客户端的迁移BreakClients(Hash)要求携带合法MigrationToken证明发布者已明确知悉并确认破坏性变更。MigrationToken由数据库 identity、旧模块哈希、新模块哈希三者拼接后哈希生成crates/schema/src/auto_migrate.rs。源码注释特别说明该令牌只是 UX 层面的防误操作手段不是安全机制——它不包含任何密钥任何人根据公开输入都能复现仅用于表达用户意图而非授权。处理禁止变更--delete-data与增量迁移--delete-data重置数据库仅限开发对于开发和测试你可以用spacetime publish --delete-data完全重置数据库但不应在生产环境使用因为它会永久删除全部数据。该参数定义于 crates/cli/src/common_args.rs别名--clear-database短选项-c支持两种取值# 默认行为不写值等价于 always # 发布前先 DESTROY 该模块关联的所有数据 spacetime publish my-db --delete-data # 仅当出现破坏性 schema 变更时才清库 spacetime publish my-db --delete-dataon-conflict从实现看--delete-data对应ClearMode其中ClearMode::Always会在发布前直接进入confirm_and_clear销毁流程而ClearMode::Never时若 pre-publish 返回ManualMigrate需要手动迁移CLI 会打印原因并中止报错信息为Aborting because publishing would require manual migration or deletion of data and --delete-data was not specified.配合--yesdelete-data可跳过销毁确认spacetime publish my-db --delete-data --yesdelete-data增量迁移生产环境推荐的复杂变更模式如果需要执行自动迁移不支持的结构变更请参阅 增量迁移指南它提供了一套零停机、无数据丢失的生产级模式。该模式的核心思路由 Lightfox Games 总结并贡献给 SpacetimeDB 社区不改表而是新增一张带目标 schema 的新表例如character_v2模块每次访问数据时先查新表命中说明已迁移未命中则从旧表读取、即时计算并写入新表后使用尽可能在写新表时同步更新旧表让旧客户端继续正常工作。其三大优势是借助 SpacetimeDB 模块热替换hotswappingspacetime publish即可完成零停机更新新表会随着使用逐步填充摊薄迁移成本行的转换与新列计算分散到多个事务中只在需要时才迁移到新表多数情况下新旧客户端可共存客户端可按自己的节奏升级。最佳实践开发阶段早期开发阶段数据丢失可接受时可自由使用--delete-data在应用到生产数据库前用示例数据测试迁移考虑为开发、预发布staging、生产分别建立独立数据库。生产环境仔细规划 schema 变更动手前先对照上述迁移兼容规则与客户端更新协调涉及潜在破坏性变更时确保客户端已准备好处理新 schema使用特性开关feature flags新增功能时可在 reducer 中引入特性开关实现渐进式发布保持向后兼容尽量新增表/reducer而不是修改现有对象记录破坏性变更维护 schema 变更的 changelog便于客户端团队跟进。复杂迁移策略对于自动迁移无法直接支持的复杂 schema 变更推荐四步走先做增量变更先新增表/列再移除旧对象双写过渡期dual-write period过渡期同时写入新旧 schema分阶段发布staged rollout客户端先切换到读取新 schema同时继续支持旧 schema清理旧 schema所有客户端升级完成后再移除废弃的表/列。客户端兼容性说明自动迁移期间活跃客户端连接会保持订阅持续正常运作客户端可能观察到定时 reducer如游戏循环的短暂中断新版模块可能移除或修改 reducer调用它们的客户端会收到运行时错误客户端不会自动感知 schema 变化——你可能需要重新生成并更新客户端 bindings例如 Rust/C#/TypeScript SDK 生成的访问器代码。测试与验证仓库中的自动迁移冒烟测试仓库在 crates/smoketests/tests/standalone/auto_migration.rs 和 crates/smoketests/tests/cluster/auto_migration.rs 中提供了完整的自动迁移端到端测试配套的测试模块位于 crates/smoketests/modules 下包括auto-migration-simple/auto-migration-incompatible基础自动迁移与不兼容变更的拒绝路径auto-migration-add-columns/auto-migration-add-columns-again追加列含带默认值的新列的迁移auto-migration-with-primary-key/auto-migration-without-primary-key(-v2)主键相关变更auto-migration-add-table-initial/auto-migration-add-table-updated新增表auto-migration-event-table-before/after、auto-migration-drop-event-table-before/after事件表event table的增删与重启后的 commitlog 回放回归验证。例如automigrate_drop_event_table_replays_after_restart测试验证了删除事件表后重启服务器commitlog 回放不会因表定义缺失而失败数据库仍可正常读写。这些测试从工程层面印证了自动迁移的持久化正确性。未来改进方向SpacetimeDB 团队正在增强迁移能力包括支持更复杂的 schema 转换面向表修改的数据迁移脚本更好的迁移影响预览工具自动化的客户端兼容性检查。小结SpacetimeDB 的自动迁移把安全变更零成本热更新、破坏性变更显式确认、禁止变更直接拒绝三者清晰分层日常迭代中你几乎可以只靠spacetime publish完成升级遇到重命名列、改类型、增删主键/唯一约束等结构性变化时则需借助--delete-data仅限开发或增量迁移模式以零停机方式演进 schema。发布前留意 pre-publish 打印的迁移计划配合先增量、后清理的策略就能在保持数据与客户端兼容的前提下持续迭代你的模块。【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表