PostgreSQL 18.4 数据库整库迁移实战:pg_dump 备份与 pg_restore 恢复完整操作手册

一、迁移环境及操作原则

项目 源库(生产) 目标库(UAT)
PostgreSQL 版本 18.4 18.4
主库 IP(示例) 192.0.2.10 192.0.2.20
备库 IP(示例) --- 192.0.2.21
数据库名称 appdb appdb
业务账号 appuser appuser
迁移方式 pg_dump 备份 pg_restore 恢复

迁移原则:

  • 使用 pg_dump -Fc 导出完整业务数据库。

  • 目标库提前安装与源库兼容的 PostgreSQL 版本及扩展。

  • 提前创建目标库需要的数据库角色,尽量保留原始属主和授权。

  • 只在目标主库恢复一次;已有物理备库通过流复制同步。

  • 生产数据库只执行查询及备份,不进行数据修改。

以下使用示例 IP、数据库名及账号。实际操作时按环境替换。


二、源数据库检查

执行位置:源库主服务器

切换 PostgreSQL 用户:

复制代码
su - postgres
psql --version
pg_dump --version

连接数据库:

复制代码
psql -X -d appdb

1. 查询数据库版本、字符集及排序规则

复制代码
SHOW server_version;

SELECT
    datname,
    pg_encoding_to_char(encoding) AS encoding,
    datcollate,
    datctype,
    datlocprovider,
    pg_get_userbyid(datdba) AS db_owner
FROM pg_database
WHERE datname = current_database();

2. 查询源库已使用的扩展及版本

复制代码
SELECT extname, extversion
FROM pg_extension
ORDER BY extname;

重点: 保存查询结果,目标主库和备库必须提前准备好所需扩展软件及兼容版本。

本次迁移使用了 PostGIS、TimescaleDB、Apache AGE、pglogical 等扩展。具体安装过程不在本文展开。

3. 查询数据库大小及表数量

复制代码
SELECT pg_size_pretty(pg_database_size(current_database()));

SELECT schemaname, COUNT(*) AS table_count
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog','information_schema')
  AND schemaname NOT LIKE 'pg_toast%'
GROUP BY schemaname
ORDER BY schemaname;

4. 检查业务账号与对象属主

复制代码
SELECT rolname, rolcanlogin, rolsuper
FROM pg_roles
WHERE rolname = 'appuser';

SELECT n.nspname AS schema_name,
       pg_get_userbyid(c.relowner) AS owner_name,
       COUNT(*) AS table_count
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r','p')
  AND n.nspname NOT LIKE 'pg_%'
GROUP BY n.nspname, c.relowner
ORDER BY 1,2;

记录业务账号和对象属主。如果还有其他对象所有者或 ACL 授权涉及的角色,也需提前准备。

退出:

复制代码
\q

三、目标数据库提前准备

执行位置:目标主库

1. 检查数据库及扩展

复制代码
su - postgres
psql --version

进入数据库:

复制代码
psql -X -d postgres

执行:

复制代码
SHOW server_version;
SHOW shared_preload_libraries;

SELECT name, default_version
FROM pg_available_extensions
ORDER BY name;

确认:

  • PostgreSQL 版本符合迁移要求。

  • 源库所需扩展均已安装且版本兼容。

  • TimescaleDB 等需要预加载的扩展已正确配置并生效。

  • 目标主库、备库均具备相应扩展软件文件。

2. 创建业务账号

在目标实例中提前创建源库所需角色。

复制代码
CREATE ROLE appuser LOGIN;

设置目标环境密码:

复制代码
\password appuser

其他被备份对象引用的角色也需要提前创建,避免恢复过程中出现 role does not exist。

3. 创建目标数据库

以下为本次迁移所用 UTF8、zh_CN.utf8 环境的示例:

复制代码
CREATE DATABASE appdb
WITH
    OWNER = postgres
    ENCODING = 'UTF8'
    LC_COLLATE = 'zh_CN.utf8'
    LC_CTYPE = 'zh_CN.utf8'
    TEMPLATE = template0;

注意: 字符集、Locale Provider、排序规则和数据库属主应以源库查询结果为准。以上命令仅适用于对应的 libc Locale 环境;使用 ICU 等其他配置时必须调整。

至此,目标环境应具备:

  • 空的目标业务数据库。

  • 所需业务角色。

  • 所需扩展和依赖。

  • 足够的数据库存储空间。


四、源库执行 pg_dump 全库备份

执行位置:源库主服务器

复制代码
mkdir -p /app/pg_dump

DB=appdb
DUMP="/app/pg_dump/${DB}_$(date +%Y%m%d_%H%M%S).dump"

pg_dump \
  -U postgres \
  -d "$DB" \
  -Fc \
  -v \
  -f "$DUMP" \
  2>"${DUMP}.log"

echo "BACKUP_EXIT_CODE=$?"
ls -lh "$DUMP"

正常结果:

复制代码
BACKUP_EXIT_CODE=0

确认归档可以读取:

复制代码
pg_restore -l "$DUMP" | head -20

计算文件校验值:

复制代码
sha256sum "$DUMP"

关键说明:

  • -Fc:自定义格式备份,供 pg_restore 使用。

  • 备份的是 appdb 整个数据库,包括业务表、数据、索引、视图、函数等数据库对象。

  • pg_dump 不备份实例级角色和密码。

  • 正常备份无需停止生产数据库,建议业务低峰期执行。


五、传输备份文件

首先在目标服务器准备目录并保证接收账号具有写入权限:

复制代码
mkdir -p /app/pg_dump

在源库服务器执行:

复制代码
scp -P 22 "$DUMP" \
  postgres@192.0.2.20:/app/pg_dump/

22 为示例 SSH 端口,按实际环境修改。

传输完成后,在目标服务器执行:

复制代码
ls -lh /app/pg_dump/
sha256sum /app/pg_dump/appdb_YYYYMMDD_HHMMSS.dump

与源库 SHA256 对比,确认文件一致。


六、目标库执行 pg_restore 整库恢复

执行位置:目标主库,postgres 用户

1. 本次使用 TimescaleDB,先进入恢复模式

复制代码
psql -X -v ON_ERROR_STOP=1 -d appdb \
  -c "CREATE EXTENSION IF NOT EXISTS timescaledb;"

psql -X -v ON_ERROR_STOP=1 -d appdb \
  -c "SELECT timescaledb_pre_restore();"

未使用 TimescaleDB 的普通 PostgreSQL 数据库,不需要执行 TimescaleDB 专用步骤。

2. 正式恢复完整数据库

将 DUMP 替换成目标服务器上的真实文件名。

复制代码
DB=appdb
DUMP=/app/pg_dump/appdb_YYYYMMDD_HHMMSS.dump
LOG=/tmp/appdb_restore.log

pg_restore \
  -U postgres \
  -d "$DB" \
  --single-transaction \
  --exit-on-error \
  -v "$DUMP" >"$LOG" 2>&1

RC=$?

echo "RESTORE_EXIT_CODE=$RC"

if [ "$RC" -ne 0 ]; then
    grep -n -m 1 -A 5 'ERROR:' "$LOG"
fi

tail -20 "$LOG"

3. 退出 TimescaleDB 恢复模式

只要前面成功进入了 TimescaleDB 恢复模式,无论数据恢复是否成功,都需要执行后处理:

复制代码
psql -X -v ON_ERROR_STOP=1 -d appdb \
  -c "SELECT timescaledb_post_restore();"

恢复成功的判断标准:

复制代码
RESTORE_EXIT_CODE=0

同时确认 TimescaleDB 后处理成功、恢复日志不存在导致中断的错误。

关于恢复参数的重要经验

本次实际迁移曾使用:

复制代码
--no-owner --no-acl

结果数据虽然恢复成功,但是还需要重新处理业务表属主、Schema 授权及序列权限。

以后为了缩短迁移时间,建议提前准备源库所需角色,优先采用上面的恢复命令,不加 --no-owner --no-acl**,保留原始对象属主和 ACL。**

只有明确决定重新规划目标库权限时,才考虑使用这两个参数。

如果恢复报错:

复制代码
ERROR: role "appuser" does not exist

先在目标实例创建对应角色,再重新恢复。使用 --single-transaction 时,失败恢复事务中的修改会回滚,但事务之外预先创建的数据库、扩展和角色仍会保留。


七、恢复完成后快速验收

1. 检查扩展

复制代码
SELECT extname, extversion
FROM pg_extension
ORDER BY extname;

与源库检查结果对比。

2. 检查业务表数量

复制代码
SELECT schemaname, COUNT(*) AS table_count
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog','information_schema')
  AND schemaname NOT LIKE 'pg_toast%'
GROUP BY schemaname
ORDER BY schemaname;

与源库备份前结果对比。

3. 检查 TimescaleDB 超表

仅使用 TimescaleDB 时执行:

复制代码
SELECT hypertable_schema, hypertable_name
FROM timescaledb_information.hypertables
ORDER BY 1,2;

4. 检查业务账号登录

在目标服务器执行:

复制代码
psql -h 192.0.2.20 -p 5432 \
  -U appuser -d appdb -W

连接成功后:

复制代码
SELECT current_user, current_database();

再使用业务账号抽查业务表和必要的函数、视图及读写权限。

5. 检查主备复制(存在备库时)

主库执行:

复制代码
SELECT application_name, client_addr, state, sync_state
FROM pg_stat_replication;

正常应显示备库为 streaming。

备库执行:

复制代码
SELECT pg_is_in_recovery();

正常物理备库返回 t。

6. 插入测试记录验证主备数据同步

仅在目标 UAT 环境执行。

主库创建测试表:

复制代码
CREATE TABLE public.sync (
    id BIGINT PRIMARY KEY,
    ts TIMESTAMPTZ DEFAULT clock_timestamp()
);

主库插入:

复制代码
INSERT INTO public.sync (id) VALUES (1);

备库查询:

复制代码
SELECT * FROM public.sync ORDER BY id DESC;

备库能够查询到刚才插入的记录,即该次数据同步验证成功。

表可以保留,后续检查只需要插入新的 ID 再到备库查询。


八、迁移完成检查清单

  • 源库和目标库 PostgreSQL 版本已核对。

  • 源库扩展、字符集和 Locale 已核对。

  • 目标扩展及所需角色提前准备完成。

  • pg_dump 备份成功,退出码为 0。

  • 备份文件传输成功,SHA256 一致。

  • pg_restore 恢复成功,退出码为 0。

  • 扩展、Schema、表、关键数据及特殊对象检查通过。

  • 业务账号登录、权限及业务 SQL 验证通过。

  • 主备复制及测试数据同步验证通过(如适用)。

九、总结

PostgreSQL 单数据库整库迁移的核心流程:

源库检查 → 目标准备 → pg_dump 备份 → 传输校验 → pg_restore 恢复 → 权限检查 → 业务及主备验收。

本次实际迁移最值得保留的经验只有三点:

  1. 先查扩展。 目标库提前安装对应扩展,不要等恢复报错再处理。

  2. 先建角色。 尽量保留源库属主和权限,避免恢复完成后大量手工授权。

  3. 恢复后验证。 pg_restore 成功只是第一步,还需确认业务账号、数据对象和主备同步正常。

这套流程适用于版本兼容、目标环境已准备好的 PostgreSQL 单数据库逻辑整库迁移。实际执行前仍需根据数据量、资源负载和业务一致性要求确定备份及恢复时间窗口。

相关推荐
AOI小白新手上路1 小时前
autodl常用的tar 打包下载(数据集)命令手册:逐段拆解与套用模板
java·大数据·数据库
凯歌的博客2 小时前
DuckDB 是一款进程内的分析型数据库
数据库·ai编程
无人生还别怕2 小时前
如何安装任意版本docker
运维·docker·容器
dishugj2 小时前
Oracle物理体系结构
数据库·oracle
北亚数据恢复2 小时前
【数据库数据恢复】NDF文件变0KB、数据库损坏?超大数据库数据恢复案例
数据库·oracle
土星云SaturnCloud2 小时前
土星云智慧服务区方案:AI视觉+边缘计算+视频存管一体化的全场景智能化落地解析
服务器·人工智能·ai·边缘计算
T0uken2 小时前
Colab:SSH 访问免费 GPU Server
运维·ssh
Python大数据分析@3 小时前
通过 MCP 实现 AI Agent自动化数据采集
运维·人工智能·爬虫·自动化