Docker 版 PostgreSQL 从 17 升级到 18

  1. 先给 17 做一次一致性快照
docker exec -i pg17 pg_dumpall -U postgres > /tmp/full.sql
  1. 停旧容器(不写 -v 不会删数据卷)
docker stop pg17
  1. 启动 pg18 (启用新的挂载卷)

注意 PG18 数据目录变了

docker run -d --name pg18 \
  -e POSTGRES_PASSWORD=原来的密码 \
  -p 5432:5432 \
  -v pg18:/var/lib/postgresql/18/data \   # 复用旧卷
  postgres:18.0
  1. 数据导入
docker exec -i pg18 psql -f dump.sql

附录

官方升级参考文档
https://www.postgresql.org/about/news/postgresql-18-released-3142/

大模型对该文章的解读


从 PostgreSQL 17 升级到 18,你有三种主流方案可选,具体取决于你对“停机时间”的容忍度、数据库大小和基础设施能力。下面按“从简到繁”逐一说明,并给出官方推荐步骤和注意事项。


✅ 方案一:pg_upgrade(最快,分钟级停机,适合单机或中小库)

核心思路:原地或并行安装 18,用 pg_upgrade 把 17 的数据文件“链”或“复制”到新集群,再切换端口/软链。
停机窗口:3–10 min(主要花在启动新实例、验证)。
前置条件

  1. 17 与 18 二进制并存(RPM/DEB 已提供 postgresql17 / postgresql18 包;Docker 可用不同 tag)。
  2. 两集群数据目录在同一文件系统,才能用 --link--swap 秒级迁移。
  3. 已安装所有旧集群用到的扩展(.so 文件版本需匹配 18)。

官方步骤(可只读校验,无需停老库)

# 1. 备份
pg_dumpall -f /safe/backup.sql      # 兜底,可选

# 2. 停 17 库
systemctl stop postgresql@17-main

# 3. 初始化 18 新库(编码/locale 要与旧库一致)
/usr/pgsql-18/bin/initdb -D /var/lib/pgsql/18/data \
  --encoding=UTF8 --locale=en_US.UTF-8

# 4. 兼容性预检(可在线)
/usr/pgsql-18/bin/pg_upgrade --check \
  --old-datadir /var/lib/pgsql/17/data \
  --new-datadir /var/lib/pgsql/18/data \
  --old-bindir /usr/pgsql-17/bin \
  --new-bindir /usr/pgsql-18/bin

# 5. 正式升级(--link 秒级,--jobs 并行)
/usr/pgsql-18/bin/pg_upgrade --link --jobs=$(nproc) \
  --old-datadir …  --new-datadir … \
  --old-bindir …   --new-bindir …

# 6. 切换环境
systemctl disable postgresql@17-main
systemctl enable  postgresql@18-main
systemctl start   postgresql@18-main

# 7. 收集统计信息 & 删除旧集群
./analyze_new_cluster.sh
./delete_old_cluster.sh

注意

  • 若使用 Docker,官方镜像从 18 起把 PGDATA 改成 /var/lib/postgresql/18/data,需同步修改卷挂载点,否则 pg_upgrade 会找不到目录。
  • 升级后务必 VACUUM FREEZEautovacuum 触发一次,以利用 18 新冻结策略。
  • 如果旧库启用了自定义表空间,确保在相同路径存在且为空,否则 --check 会失败。

✅ 方案二:pg_dumpall + restore(最稳,小时级停机,适合 <100 GB)

核心思路:逻辑全量导出 SQL,再导入新集群;零依赖、跨平台、最保险。
停机窗口:导出+导入耗时(网络/磁盘决定)。
步骤

  1. 停应用 → 只读事务结束。
  2. pg_dumpall -v -f dump.sql
  3. 起 18 新实例,psql -f dump.sql 导入。
  4. 验证用户/扩展/序列,重设密码、重新授权。
  5. 切换连接串到 18,启动应用。
    优点:简单、可跨大版本、可编辑 SQL 清理垃圾。
    缺点:大库慢;大对象、编码错误需手动处理。

✅ 方案三:逻辑复制(近零停机,适合 SLA 严格或大库)

核心思路:17 当主库持续对外服务,18 当逻辑从库追平后秒级切换。
停机窗口:秒级(仅切换 VIP/DNS)。
简化流程

  1. 17 主库:ALTER SYSTEM SET wal_level=logical; 重启。
  2. 创建 PUBLICATION alltables FOR ALL TABLES;
  3. 部署 18 空库,用 pg_createsubscriber --publisher-server=... --subscription=sub1 一键建成逻辑从库。
  4. 观察 pg_stat_subscription.replay_lsn 追上主库。
  5. 停应用写入 → 确认无延迟 → 提升 18 为主(pg_ctl promote)。
  6. 改连接串 → 启动应用 → 拆除旧 17。
    注意
  • 所有表须有主键或 REPLICA IDENTITY FULL
  • 大事务期间需保证 WAL 保留足够长。
  • 序列不同步,切换后需手动 setval() 补差。

升级后必做清单(无论哪种方案)

  1. 回归测试:重点验证
    • 虚拟生成列、UUIDv7、新排序规则 pg_unicode_fast 等 18 新特性是否影响业务。
  2. 更新客户端驱动:JDBC 42.7+、libpq 18 建议配套,避免协议 3.2 兼容问题。
  3. 统计信息:立即 ANALYZE 或打开 auto-analyze,防止计划退化。
  4. 配置 diff:用 pg_upgrade 生成的 *.conf.sample 比对,把 17 自定义参数同步到 18。
  5. 备份策略:确认新集群 WAL 归档、定时全量策略已生效。
  6. 清理:删除旧集群、旧 RPM/DEB、旧 Docker volume,避免误启动。

一句话选型

  • 能停 10 分钟、单节点pg_upgrade --link 最快。
  • <100 GB、想最稳pg_dumpall 逻辑导出。
  • TB 级、24×7 不能停 → 逻辑复制蓝绿升级。

按上面步骤执行,即可把 PostgreSQL 17 平滑带到 18,享受 AIO、跳过扫描、并行 GIN 等性能红利。祝你升级顺利!

评论栏