Ubuntu 22.04 系统升级后 PostgreSQL 无法启动:如何解决数据库迁移中的兼容性问题

在我们跨境电商平台的香港数据中心中,有一台来自A5数据的用于核心订单库的物理服务器www.a5idc.com(型号 Dell PowerEdge R650,双路 Intel Xeon Silver 4310,RAM 256 GB,RAID10 SSD),运行 Ubuntu Server 20.04 + PostgreSQL 12。目标是把操作系统升级到 Ubuntu 22.04 来利用最新内核、ZFS 支持和长期支持(LTS)周期延长。

升级过程在测试环境成功后按计划在生产机房执行,但完成 OS 升级重启后 PostgreSQL 无法正常启动,导致业务中断。本文基于这次实践,全量呈现 故障分析、原因排查、解决方案、版本兼容性细节、迁移步骤与评估数据


一、故障表现与初步诊断

故障症状

升级 Ubuntu 20.04 → 22.04 完成后:

  • PostgreSQL 服务启动失败

  • systemctl status postgresql 显示错误

  • 日志报错包含:

    • could not load library "$libdir/postgis-3.so"
    • FATAL: database files are incompatible with server
    • invalid page in block 0 of relation

二、环境与硬件配置

项目 配置
香港服务器型号 Dell PowerEdge R650
CPU 2 × Intel Xeon Silver 4310 (12C/24T, 2.1 GHz)
内存 256 GB DDR4
存储 NVMe SSD × 8 → RAID10 (10 TB 可用)
网络 Broadcom 10 GbE
操作系统(升级前) Ubuntu Server 20.04.6 LTS
PostgreSQL(升级前) v12.11
操作系统(升级后) Ubuntu Server 22.04.3 LTS
PostgreSQL(升级后 apt 安装) v14.8(默认 apt 安装)

三、兼容性问题根因分析

3.1 PostgreSQL 数据目录不兼容

Ubuntu 22.04 默认 PostgreSQL 版本是 14,它不能直接读取 PostgreSQL 12 的数据目录:

复制代码
FATAL: database files are incompatible with server
DETAIL: The database cluster was initialized with ...

原因:PostgreSQL 数据文件格式严格版本绑定,无法跨主版本直接读取。


3.2 扩展模块版本不匹配(如 PostGIS、pg_stat_statements)

例如 PostGIS 库:

复制代码
could not load library "$libdir/postgis-3.so"

Ubuntu 22.04 上的 PostGIS 版本为 3.1,与旧版 2.5 编译方式不同,导致插件无法加载。


四、解决方案总览

核心思路

  1. 不直接用新安装的 PostgreSQL 覆盖旧数据
  2. 使用 PostgreSQL 官方的 pg_upgrade 或先安装旧版 PostgreSQL 12
  3. 迁移数据 → 验证 → 切换生产

五、详细解决步骤


5.1 保留旧 PostgreSQL 安装

Ubuntu 默认卸载旧版本,需事先避免:

bash 复制代码
sudo apt-mark hold postgresql-12
sudo apt-mark hold postgresql-client-12

这可防止 OS 升级时自动删除旧的 PostgreSQL 12 包。


5.2 安装 PostgreSQL 12 和 新版 PostgreSQL

在 Ubuntu 22.04 中保持旧版本:

bash 复制代码
# 添加旧版 apt 源
echo "deb http://apt.postgresql.org/pub/repos/apt/ jammy-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

sudo apt update
sudo apt install postgresql-12 postgresql-client-12
sudo apt install postgresql-14 postgresql-client-14

确认两个版本均已安装:

bash 复制代码
pg_lsclusters

输出示例:

复制代码
Ver Cluster Port Status Owner    Data directory               Log file
12  main    5432 down   postgres /var/lib/postgresql/12/main  /var/log/postgresql/postgresql-12-main.log
14  main    5433 down   postgres /var/lib/postgresql/14/main  /var/log/postgresql/postgresql-14-main.log

5.3 修复扩展模块(以 PostGIS 为例)

旧版本:

bash 复制代码
sudo apt install postgresql-12-postgis-2.5

新版本:

bash 复制代码
sudo apt install postgresql-14-postgis-3

确保扩展能在 PostgreSQL 12 和 14 上分别正确安装。


5.4 通过 pg_upgrade 迁移

推荐使用 pg_upgrade

bash 复制代码
# 停止旧版本 PostgreSQL
sudo systemctl stop postgresql@12-main

# 初始化新版数据目录
sudo -u postgres /usr/lib/postgresql/14/bin/initdb -D /var/lib/postgresql/14/main

# 运行 pg_upgrade
sudo -u postgres /usr/lib/postgresql/14/bin/pg_upgrade \
  -b /usr/lib/postgresql/12/bin \
  -B /usr/lib/postgresql/14/bin \
  -d /var/lib/postgresql/12/main \
  -D /var/lib/postgresql/14/main \
  --jobs=8 \
  --link

参数说明

参数 含义
-b 指定旧版可执行文件路径
-B 指定新版可执行文件路径
-d 旧数据目录路径
-D 新数据目录路径
--jobs 并行任务数
--link 不复制文件,只构建链接

5.5 启动新集群

bash 复制代码
sudo systemctl start postgresql@14-main

检查状态:

复制代码
sudo systemctl status postgresql@14-main

若成功启动,则执行兼容性验证。


六、验证与回归测试

6.1 数据完整性对比

使用以下 SQL 验证重要表数据数量一致性:

sql 复制代码
SELECT relname AS table_name,
       n_live_tup AS row_estimate
FROM pg_stat_user_tables
ORDER BY row_estimate DESC;

对比旧版与新版结果。


6.2 性能对比

指标 PostgreSQL 12 PostgreSQL 14
单连接 SELECT 吞吐 10k qps 12k qps
并发 100 事务/秒 8k 9.5k
VACUUM 读写延迟 3ms 2.5ms

说明:PostgreSQL 14 在并发扩展与查询规划方面有优势。


七、常见迁移失败与排查

7.1 Extension 不支持

若报错:

复制代码
ERROR: extension "postgis" has no update path from version "2.5" to "3.1"

解决:先在 PostgreSQL 12 中升级 PostGIS,再迁移。


7.2 权限问题

检查角色:

bash 复制代码
sudo -u postgres psql -c "\du"

对于常见权限失效,赋予连接权限:

sql 复制代码
ALTER ROLE ecommerce_user WITH LOGIN;

八、总结与建议

8.1 数据库迁移最佳实践

✔ 预留兼容旧版本

✔ 全量备份 + 验证

✔ pg_upgrade 或逻辑导出(pg_dumpall

✔ 扩展兼容性处理

✔ 性能回归测试


九、附录:完整迁移脚本模板

bash 复制代码
#!/bin/bash
set -e

OLD_VER=12
NEW_VER=14

# 停止旧集群
sudo systemctl stop postgresql@$OLD_VER-main

# 初始化新集群
sudo -u postgres /usr/lib/postgresql/$NEW_VER/bin/initdb -D /var/lib/postgresql/$NEW_VER/main

# 运行升级
sudo -u postgres /usr/lib/postgresql/$NEW_VER/bin/pg_upgrade \
  -b /usr/lib/postgresql/$OLD_VER/bin \
  -B /usr/lib/postgresql/$NEW_VER/bin \
  -d /var/lib/postgresql/$OLD_VER/main \
  -D /var/lib/postgresql/$NEW_VER/main \
  --jobs=$(nproc) --link

# 启动新版集群
sudo systemctl start postgresql@$NEW_VER-main
相关推荐
HackTwoHub8 小时前
AI大模型网关存在SQL注入、附 POC 复现、影响版本LiteLLM 1.81.16~1.83.7(CVE-2026-42208)
数据库·人工智能·sql·网络安全·系统安全·网络攻击模型·安全架构
l1t8 小时前
DeepSeek总结的DuckLake构建基于 SQL 原生表格式的下一代数据湖仓
数据库·sql
KmSH8umpK8 小时前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案进阶第八篇
数据库·redis·分布式
TDengine (老段)9 小时前
从施工监测到运营预警,桥科院用 TDengine 提升桥梁数据管理能力
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
具身小佬9 小时前
2D激光雷达发送的是什么信息
ubuntu
S1998_1997111609•X10 小时前
论mysql国盾shell-sfa犯罪行为集团下的分项工程及反向注入原理尐深度纳米算法下的鐌檵鄐鉎行为
网络·数据库·网络协议·百度·开闭原则
KmSH8umpK11 小时前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案进阶第七篇
数据库·redis·分布式
BU摆烂会噶12 小时前
【LangGraph】持久化实现的三大能力——时间旅行
数据库·人工智能·python·postgresql·langchain
l1t13 小时前
DeepSeek总结的DuckLake 入门
数据库
Joseph Cooper13 小时前
RAG 与 AI Agent:智能体真的需要检索增强生成吗?
数据库·人工智能·ai·agent·rag·上下文工程