- 文档
- 教程
- 知识库
【免费下载链接】til
:memo: Today I Learned
pg_upgrade是 PostgreSQL 内置的跨大版本升级工具,相比pg_dump+pg_restore的全量导出再导入,它直接对数据文件进行版本迁移,速度更快、手工步骤更少。但在正式执行升级前,务必先用--check参数做一次"干跑"(dry-run),让工具对旧集群与新集群执行一系列一致性检查,确认两者兼容后再真正动手。读完本文,你将掌握pg_upgrade四个核心路径参数的用法、--check预检的完整流程,以及如何解读检查输出并处理不兼容问题。
为什么优先选择 pg_upgrade 而非 dump/restore
升级 PostgreSQL 数据库服务器版本时,常见的有两条路线:
pg_dump+pg_restore:把数据逻辑导出为文件再导入新集群。流程直观,但需要额外的中间步骤,且大库的导出导入耗时长。pg_upgrade:PostgreSQL 自带的就地升级工具(本仓库 dump-and-restore-a-database.md 介绍了前一种方式的完整用法,可作为对比参照)。它直接迁移物理数据文件,通常更快、需要的人工步骤更少,是官方推荐的常规大版本升级方式。
正是因为pg_upgrade直接操作数据文件,风险更高,所以升级前的兼容性预检就显得格外重要。
理解四个核心路径参数
运行pg_upgrade前,必须先准备好一套旧的(当前)集群和一套新的(目标)集群,然后通过以下四个参数把它们告诉工具:
| 参数 | 作用 | 取值示例 |
|---|---|---|
--old-bindir | 旧版本 PostgreSQL 可执行文件(bin)所在目录 | $HOME/.asdf/installs/postgres/12.3/bin |
--new-bindir | 新版本 PostgreSQL 可执行文件(bin)所在目录 | /usr/local/opt/postgresql@13/bin |
--old-datadir | 旧集群的数据目录(data directory) | $HOME/.asdf/installs/postgres/12.3/data |
--new-datadir | 新集群的数据目录 | ./postgres/data |
其中--new-datadir指向的新集群必须先存在——它通常是用新版本 bin 目录下的initdb初始化出来的空集群。本仓库的 create-a-cluster-in-a-specific-data-directory.md 演示了如何用/usr/local/opt/postgresql@13/bin/initdb -D postgres/data在应用目录旁初始化一个 UTF-8 编码的新集群,这正是--new-datadir ./postgres/data的来源。
值得注意的是,示例命令中旧集群来自asdf安装的 PostgreSQL 12.3($HOME/.asdf/installs/postgres/12.3/),新集群来自 Homebrew 安装的postgresql@13(/usr/local/opt/postgresql@13/)——说明pg_upgrade完全不关心你用什么方式安装 PostgreSQL,只要给出两个版本各自的 bin 和 data 目录即可。关于多版本安装管理,可参考 manage-major-versions-with-brew-and-direnv.md 与 switch-the-running-postgres-server-version.md。
用 --check 做兼容性预检(干跑)
正式执行升级之前,正确的做法是:把你最终要执行的pg_upgrade命令原样写好,然后在末尾追加--check。加了这个参数后,工具不会真的迁移数据,只会做一次 dry-run——执行一系列一致性检查并报告结果,帮助你提前发现潜在的升级障碍。
提示:命令中的
\是 shell 续行符,方便在终端里分行书写长命令;去掉\写成单行效果相同。
下面是原文档中一个成功的预检示例(从 PostgreSQL 12.3 升级到 13):
$ /usr/local/opt/postgresql@13/bin/pg_upgrade \ --old-bindir $HOME/.asdf/installs/postgres/12.3/bin \ --new-bindir /usr/local/opt/postgresql@13/bin \ --old-datadir $HOME/.asdf/installs/postgres/12.3/data \ --new-datadir ./postgres/data \ --check Performing Consistency Checks ----------------------------- Checking cluster versions ok Checking database user is the install user ok Checking database connection settings ok Checking for prepared transactions ok Checking for system-defined composite types in user tables ok Checking for reg* data types in user tables ok Checking for contrib/isn with bigint-passing mismatch ok Checking for presence of required libraries ok Checking database user is the install user ok Checking for prepared transactions ok Checking for new cluster tablespace directories ok *Clusters are compatible*注意这里调用的是新版本 bin 目录下的pg_upgrade(/usr/local/opt/postgresql@13/bin/pg_upgrade),这是官方推荐的做法——用目标版本的工具去升级。
逐行解读一致性检查输出
--check会依次对两个集群执行多项检查,每一项都输出一行状态。上面这个成功样例中各行含义如下:
- Checking cluster versions:确认旧集群版本低于新集群版本,且两者属于受支持的升级跨度。
- Checking database user is the install user:确认执行升级的操作系统用户与集群数据目录的属主一致(
pg_upgrade要求数据文件归当前用户所有)。该检查在输出中出现了两次,属于工具检查列表的正常现象。 - Checking database connection settings:尝试连接新旧集群,验证连接配置可用。
- Checking for prepared transactions:检查集群中是否存在未提交的两阶段提交(prepared transaction),存在则升级会被阻止。
- Checking for system-defined composite types in user tables:检查用户表中是否引用了系统内置的复合类型,这类引用在大版本间可能导致二进制不兼容。
- Checking for reg* data types in user tables:检查用户表列中是否使用了
reg*(如regclass、regproc等)系统目录 OID 引用类型。 - Checking for contrib/isn with bigint-passing mismatch:检查 contrib 模块
isn在旧新版本间的函数参数传递是否一致。 - Checking for presence of required libraries:确认新旧集群所需的共享库(动态加载模块)在升级环境中均可找到。
- Checking for new cluster tablespace directories:若使用了表空间,检查新集群对应的表空间目录是否就绪。
当所有检查项都以ok结尾时,工具会给出最终结论:*Clusters are compatible*,表示可以放心移除--check正式执行升级。
检查不通过时如何处理
如果集群之间存在不兼容项,输出会明确报告问题所在。最常见的例子之一是新旧集群的排序规则(collation)设置不一致——比如旧集群用en_US.UTF-8初始化,而新集群用别的 locale 初始化,文本排序和索引行为就会存在差异。
遇到这类问题时,没有统一的"一键修复"办法,需要针对具体问题逐个决定处理方案,常见思路包括:
- 排序规则不一致:用与旧集群一致的 locale 重新
initdb一个新集群(参考 create-a-cluster-in-a-specific-data-directory.md 中的--locale=en_US.UTF-8用法),再重新预检。 - 存在 prepared transactions:先连接旧集群执行
COMMIT PREPARED或ROLLBACK PREPARED清理事务,再重跑预检。 - 缺少所需库/扩展:在新版本环境中先安装对应的 contrib 扩展或共享库,再重跑预检。
总之,预检输出的每一项错误都对应一类可操作的修复动作,修复后应再次运行--check直到输出*Clusters are compatible*,再进入正式升级。
升级前后的配套流程
完整的pg_upgrade升级流程通常包含以下几个阶段,本仓库的系列文档可配合使用:
- 准备多版本环境:用 asdf、Homebrew(
brew install postgresql@13)等方式安装目标版本,参考 manage-major-versions-with-brew-and-direnv.md。 - 用新版本初始化新集群:
initdb -D <new-datadir>,参考 create-a-cluster-in-a-specific-data-directory.md。 - 运行
pg_upgrade --check预检(本文核心步骤),确认输出*Clusters are compatible*。 - 停止旧服务器(用旧版本的
pg_ctl stop,参考 switch-the-running-postgres-server-version.md),移除--check正式运行升级。 - 启动新服务器并用
pg_isready验证,参考 check-if-the-local-server-is-running.md。
--check这一"先预检、再执行"的思路,是避免在升级过程中才发现不兼容、导致数据目录不可用等事故的关键防线,值得纳入每一次大版本升级的标准操作流程。
- 文档
- 教程
- 知识库
【免费下载链接】til
:memo: Today I Learned
相关推荐
Gel migration upgrade-check:用 EdgeDB/Gel 迁移工具在升级前完成 schema 兼容性预检
Gel migration upgrade check:用 EdgeDB/Gel 迁移工具在升级前完成 schema 兼容性预检 gel migration u
数据库图数据库关系型数据库TDengine 升级兼容性检查项全解:滚动升级与冷升级的验证体系(compat-check)
TDengine 升级兼容性检查项全解:滚动升级与冷升级的验证体系(compat check) 导读 TDengine 版本迭代频繁,跨版本升级(尤其滚动升级)
数据库时序数据库大数据物联网云原生Serf集群升级指南:协议兼容性与平滑升级策略
Serf集群升级指南:协议兼容性与平滑升级策略 概述 Serf作为一款分布式集群成员管理和事件通知系统,其设计初衷就是要在参与集群的各个节点上长期运行。这些节点
服务注册发现云原生集群管理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考