ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

pgroll 零停机 PostgreSQL Schema 迁移实战:从安装、基线到回滚的完整指南

pgroll 零停机 PostgreSQL Schema 迁移实战:从安装、基线到回滚的完整指南 后端数据库CLI开发工具【免费下载链接】pgrollPostgreSQL zero-downtime migrations made easy项目地址https://gitcode.com/gh_mirrors/pg/pgroll点击查看免费下载pgroll是 Xata 开源的一款 PostgreSQL 零停机、可回滚的 schema 迁移 CLI 工具它通过同时对外提供多个 schema 版本让客户端应用在数据库结构变更期间持续可用。本文将围绕仓库根目录 README.md 的完整脉络带你从安装、初始化、基线导入、启动迁移、配置客户端到完成迁移与回滚并结合仓库源码深入剖析其多版本虚拟 schema expand/contract的底层工作原理。一、为什么需要零停机 schema 迁移传统的 PostgreSQL schema 迁移如直接执行ALTER TABLE会带来两类风险一是部分操作需要获取表上的排他锁导致线上读写被阻塞二是破坏性变更删列、改名、收紧约束会让还在使用旧结构的客户端应用立刻报错。pgroll的定位就是同时解决这两个问题——它保证迁移过程不加锁、无破坏性变更并让新旧两个 schema 版本在同一时间窗口内并行可用即使迁移中包含 breaking change 也能平稳过渡。这一目标的实现基础在 README.md 中明确为为 PostgreSQL 同时提供多个 schema 版本由工具接管复杂的迁移操作确保变更不加锁、新旧版本并行工作从而显著降低迁移风险、简化客户端发布流程并支持即时回滚。二、核心特性一览根据 README.md 的 Features 列表pgroll的核心能力包括特性说明零停机迁移无数据库锁、无破坏性变更新旧版本并行迁移期间旧版与新版 schema 同时可用自动回填backfill需要时为列自动回填数据即时回滚迁移过程中出现问题可立即回退支持既有 schema无需从空库起步可用baseline导入现有结构支持 PostgreSQL 14要求 Postgres 14.0 及以上版本兼容任意托管服务包括 RDS、Aurora 等云数据库单二进制分发使用 Go 编写跨平台、无外部运行时依赖三、安装 pgrollREADME.md 提供了三种安装方式可按环境任选其一。3.1 下载预编译二进制Linux、macOS、Windows 均有官方发布的二进制直接前往 Releases 页面下载对应平台的压缩包解压即可无需安装任何运行时依赖。3.2 从源码编译安装go install github.com/xataio/pgrolllatest注意该方式要求Go 1.24 或更高版本。仓库根目录的 go.mod 与 Makefile 是本地构建的入口构建产物为单一可执行文件符合cross-platform single binary的定位。3.3 HomebrewmacOS / Linuxbrew tap xataio/pgroll brew install pgroll四、快速上手完成你的第一次迁移README.md 给出了完整的五步工作流初始化数据库 → 可选基线导入 → 启动迁移 → 配置客户端 → 完成迁移以及贯穿全程的即时回滚。4.1 准备数据库initpgroll需要在目标数据库中保存内部状态用于追踪当前 schema 版本并记录版本历史。初始化命令如下pgroll --postgres-url postgres://user:passwordhost:port/dbname init初始化逻辑见 cmd/init.goinit子命令调用roll.Roll.Init完成状态存储的配置。从源码看pgroll 会在数据库中建立pgroll状态 schema可通过全局参数--pgroll-schema改名其中包含migrations版本历史表、用于捕获指定 schema 当前结构的函数以及记录 pgroll 之外手工执行 DDL 的触发器详见 docs/tutorial.md。4.2 导入既有数据库可选baseline如果是从空数据库起步可以直接跳过本步。但如果要把pgroll用于已有数据的数据库就必须先用baseline命令导入当前结构pgroll --postgres-url postgres://user:passwordhost:port/dbname baseline 000_existing_schema ./migrations/该命令的两个参数分别是基线版本号和存放迁移文件的目标目录。其实现见 cmd/baseline.go命令会生成一个包含空raw_sql操作的占位迁移文件默认 YAML可用-j/--json切换为 JSON-y/--yes跳过交互确认再调用CreateBaseline在数据库中建立基线记录。基线的作用是让 pgroll 认识既有的 schema 结构从而把后续迁移建立在此基础之上。4.3 编写迁移文件创建迁移文件仓库 examples 目录提供了从建表、加列到改类型、建索引、加外键等数十个可直接复用的示例。以下迁移将新建一张customers表{ name: initial_migration, operations: [ { create_table: { name: customers, columns: [ { name: id, type: integer, pk: true }, { name: name, type: varchar(255), unique: true }, { name: bio, type: text, nullable: true } ] } } ] }4.4 启动迁移startpgroll --postgres-url postgres://user:passwordhost:port/dbname start initial_migration.jsonstart子命令的定义见 cmd/start.go它会先做初始化检查与基线检查若 schema 非空却无迁移历史会提示先执行baseline随后读取迁移文件并开始迁移。命令结束后数据库中会同时存在两个版本的 schema旧版本没有 customers 表与新版本有 customers 表二者并行可访问。start还支持几个与回填相关的实用参数参数默认值说明--backfill-batch-size1000见 pkg/backfill/config.go每批回填的行数--backfill-batch-delay0批次之间的间隔如1s、1000ms-c, --completefalse启动迁移后立即标记完成-s, --skip-validationfalse跳过迁移校验4.5 配置客户端应用迁移启动后客户端即可切换到新版本 schema。切换方式是把search_path设置为新版本 schema 名即pgroll start输出的版本名SET search_path TO public_initial_migration;版本 schema 的命名规则可在源码中找到start完成时根据迁移名称生成public_initial_migration这样的版本 schema 名cmd/start.go默认开启的版本 schema 行为由--use-version-schema全局参数控制。4.6 完成迁移complete当没有客户端再使用旧版本 schema 时就可以完成迁移这一步会删除旧 schemapgroll --postgres-url postgres://user:passwordhost:port/dbname completecomplete命令见 cmd/complete.go调用Roll.Complete执行所有非增量破坏性变更——删除旧表、旧列、旧索引并把新表/新列重命名为最终名称。由于视图仍然正确映射到物理表与列客户端在这一阶段依旧不受影响。4.7 回滚迁移rollback在迁移进行中的任何时刻都可以回滚到上一个版本删除新 schema让旧 schema 恢复原状。pgroll --postgres-url postgres://user:passwordhost:port/dbname rollbackrollback命令见 cmd/rollback.go成功后会提示自上个版本以来的改动已被还原。五、pgroll 的工作原理多版本虚拟 Schema5.1 视图之上的虚拟版本README.md 明确指出pgroll 通过在物理表之上创建视图来构建虚拟 schema因此可以在完全不打扰现有客户端的前提下完成迁移所需的全部变更。每个迁移对应一个新建的 Postgres schemaschema 内是对底层物理表的视图不同版本通过视图暴露不同的表与列客户端用哪个版本就映射到对应的视图。以下流程图展示了迁移期间新旧 schema 版本并行工作的整体脉络5.2 遵循 expand/contract先扩展后收缩模式迁移被拆成两个阶段start 阶段expand只做增量变更创建新表、新列、新索引等一切加性操作绝不破坏现有结构。若某变更不向后兼容例如给列加NOT NULLpgroll 会采取额外措施保证当前 schema 仍然有效——比如先给新列回填默认值。complete 阶段contract执行收缩删除旧表、旧列、旧索引实质上打破旧版本 schema。第二阶段完成后只有新 schema 保留不再需要的表与列被移除新表/新列被重命名为最终名称。由于视图始终映射到正确的物理表与列客户端在这一阶段仍持续可用。5.3 破坏性变更的处理新列 回填 触发器当某个列的变更属于 breaking change例如收紧为NOT NULL、改变类型pgroll 不会直接改原列而是在物理表中新建一个列并从旧列回填数据同时配置触发器在迁移生效期间把对旧列/新列的写入同步到对方。新列只在新版本 schema 的视图中暴露。下图展示了多个 schema 版本在迁移窗口内的并存结构5.4 源码级原理印证加列操作的增量策略以add_column为例pkg/migrations/op_add_column.go 展示了其规避排他锁的三板斧不可空列先以 nullable 方式加入、再挂NOT VALID的 check 约束待 complete 阶段校验后升级为NOT NULL列属性对应upgradeNotNullConstraintToNotNullAttributeCHECK 约束同样以NOT VALID形式延迟校验UNIQUE 则改为并发创建唯一索引、完成阶段再ADD CONSTRAINT ... USING INDEX。此外若列的 DEFAULT 表达式不满足快速路径优化见 internal/defaults/fastpath.goDEFAULT 会被推迟到 complete 阶段设置。回填与触发器的批量实现回填任务由 pkg/backfill/backfill.go 实现其Start方法按主键或唯一非空列分批更新数据批次大小由配置控制没有主键的表则退化为基于内部标记列_pgroll_needs_backfill的批量更新。迁移期间写入同步由触发器承担多个操作叠加到同一触发器的 SQL 会被重写为引用物理列名NEW._pgroll_new_xxx详见rewriteTriggerSQL。动作执行的有序性每个操作最终会转化为一系列 DBAction由 pkg/migrations/coordinator.go 中的Coordinator按加入顺序执行并保证同一动作只执行一次。六、全局参数与状态管理6.1 全局持久化参数所有子命令共享以下全局参数定义于 cmd/root.go同时支持PGROLL_前缀的环境变量由 viper 自动绑定参数环境变量默认值说明--postgres-urlPGROLL_PG_URLpostgres://postgres:postgreslocalhost?sslmodedisable数据库连接串--schemaPGROLL_SCHEMApublic执行迁移的目标 schema--pgroll-schemaPGROLL_STATE_SCHEMApgrollpgroll 内部状态 schema--lock-timeoutPGROLL_LOCK_TIMEOUT500pgroll DDL 操作的锁超时毫秒--rolePGROLL_ROLE空执行迁移时可选切换的 Postgres 角色--use-version-schemaPGROLL_USE_VERSION_SCHEMAtrue是否为每个迁移创建版本 schema--verbosePGROLL_VERBOSEfalse开启详细日志这些参数经由 cmd/flags/flags.go 读取并在 cmd/root.go 中装配进roll.Roll--lock-timeout会转化为会话级SET lock_timeout--role会执行SET ROLE--schema则被注入连接的search_path见 pkg/roll/roll.go 的setupConn。6.2 支持的 PostgreSQL 版本pgroll支持 PostgreSQL 14 及以上版本兼容 RDS、Aurora 等任何 Postgres 服务。需要注意一个版本差异docs/getting-started.md 指出在 PostgreSQL 14 中pgroll 无法以(security_invoker true)选项创建版本视图该能力自 PostgreSQL 15 起才提供因此PostgreSQL 14 下表上的行级安全RLS策略不会被 pgroll 的版本视图尊重若你在 PG14 上依赖 RLSpgroll 可能不是合适的选择。除这一点外所有特性在所有受支持版本上均可正常使用。七、性能基准README.md 说明每个提交到main的代码都会跑一轮性能基准用于追踪性能随时间的变化。基准分别在 PostgreSQL 14.8、15.3、16.4、17.0、18.0 及 latest 上运行数据量分为 10k、100k、300k 行三档Backfill以默认批策略每批 10k 行、无退避回填值为placeholder的 text 列时每秒处理的行数。WriteAmplification/NoTrigger未安装 pgroll 触发器时写表的基准吞吐rows/s。WriteAmplification/WithTrigger安装 pgroll 触发器后写表的吞吐rows/s用于量化触发器带来的写放大。ReadSchema每秒执行read_schema函数的次数该函数是迁移期间高频执行的核心函数。基准测试的本地源码位于 internal/benchmarks/benchmarks_test.go可据此了解各指标的测试口径。八、文档、贡献与许可证更多进阶用法迁移文件格式的完整操作清单见 docs/operations/README.md增删列/表、改类型、加索引与各类约束、raw_sql等概念详解见 docs/concepts.md逐步教程见 docs/tutorial.md与 ORM、客户端应用集成的指南见 docs/guides/clientapps.mdx 与 docs/guides/orms.mdxCLI 各子命令的完整参数说明见 docs/cli/README.md。贡献欢迎提交 issue、报告缺陷或提出功能请求提交代码时请 fork 仓库、新建分支、编写测试并确保通过 lint 与测试后再提 PR详见 README.md。许可证项目采用 Apache License 2.0见 LICENSE。九、总结从 README.md 出发本文完整覆盖了pgroll的安装、初始化、基线导入、迁移启动、客户端切换、完成与回滚的完整闭环并从源码层面印证了其视图之上构建多版本虚拟 schema expand/contract 两阶段迁移 新列回填与触发器同步的零停机实现机制。无论是管理既有生产库的平滑演进还是为客户端发布提供即时回滚能力pgroll都能以一条命令的形式把这些复杂操作收敛为可预期、可验证的流程。赞分享后端数据库CLI开发工具【免费下载链接】pgrollPostgreSQL zero-downtime migrations made easy项目地址https://gitcode.com/gh_mirrors/pg/pgroll点击查看免费下载相关推荐GTA 老游戏在 Win11 上闪退SilentPatch 免费兼容性修复 3 步跑起来GTA 老游戏在 Win11 上闪退SilentPatch 免费兼容性修复 3 步跑起来 重装系统后双击《圣安地列斯》加载画面都没走到就闪退玩了多年的 G游戏开发逆向工程Gutenberg InputControl 文本输入组件深度解析Props、草稿状态机与 TextControl 迁移路径Gutenberg InputControl 文本输入组件深度解析Props、草稿状态机与 TextControl 迁移路径 本文围绕 Gutenberg 中后端数据库CLI开发工具揭秘云帆培训考试系统前端VueElement UI实现答题卡、倒计时与交卷的完整代码走读揭秘云帆培训考试系统前端VueElement UI实现答题卡、倒计时与交卷的完整代码走读 本文带你走读 yftrain 在线考试系统 学习系统 / 企业培上一篇DBX 数据库结构对比与AI SQL优化实战指南如何快速定位环境差异并搞定慢查询下一篇Kubernetes Handbook 视角下的 CNCF 2020 年度报告解读从云原生生态扩张到安全认证升级创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表