游乐游手机版
首页/数据库/文章详情

如何更改PostgreSQL数据库数据存储位置的详细步骤

时间:2026-07-03 07:02
说到 PostgreSQL 的数据迁移,很多人第一反应是“把文件拷过去就行”。但实际操作中,如果漏掉几个关键步骤,轻则服务起不来,重则数据损坏。这里把完整流程拆开揉碎,从头到尾过一遍。 1 停止 PostgreSQL 服务 动手之前,先确保数据库已经完全停止,不能有任何活跃连接。否则直接操作数据目

说到 PostgreSQL 的数据迁移,很多人第一反应是“把文件拷过去就行”。但实际操作中,如果漏掉几个关键步骤,轻则服务起不来,重则数据损坏。这里把完整流程拆开揉碎,从头到尾过一遍。

更改PostgreSQL的数据存储位置的方法

1. 停止 PostgreSQL 服务

动手之前,先确保数据库已经完全停止,不能有任何活跃连接。否则直接操作数据目录,后果很难预料。

# 使用 systemctl(如果已配置)
systemctl stop postgresql-15

# 或直接使用 postmaster
kill -INT $(head -1 /var/lib/pgsql/15/data/postmaster.pid)

# 或使用 pg_ctl
/usr/pgsql-15/bin/pg_ctl stop -D /var/lib/pgsql/15/data/

2. 创建新数据目录

确定好目标路径后,先建好目录,然后调整权限。这一步容易忽略的是:目录的所有者必须是 postgres,权限必须为 700,否则启动时会直接报错。

# 例如移动到 /data/pgsql 目录
NEW_DATA_DIR="/data/pgsql/15/data"

# 创建新目录
mkdir -p "$NEW_DATA_DIR"

# 设置正确的权限(postgres 用户)
chown -R postgres:postgres "$NEW_DATA_DIR"
chmod 700 "$NEW_DATA_DIR"

3. 复制(或移动)数据文件

建议直接使用 mv,因为数据量大时复制耗时很长,且移动操作不会产生双倍空间占用。如果对原数据有顾虑,可以先用 cp -rp 复制一份,等确认新目录运行正常后再清理原目录。

# 方法1:移动数据(推荐,更快)
mv /var/lib/pgsql/15/data/* "$NEW_DATA_DIR/"

# 方法2:复制数据(保留原数据)
cp -rp /var/lib/pgsql/15/data/* "$NEW_DATA_DIR/"

4. 修改配置文件

这一步有两种思路:要么直接在 postgresql.conf 中更新 data_directory 参数,要么通过软链接“欺骗”系统。后者适合不想修改配置文件、或者需要快速回退的场景。

方法A:修改 postgresql.conf

# 编辑配置文件
vi "$NEW_DATA_DIR/postgresql.conf"

# 修改或添加以下行
data_directory = '/data/pgsql/15/data'

方法B:使用软链接(不修改配置文件)

# 备份原目录
mv /var/lib/pgsql/15/data /var/lib/pgsql/15/data_old

# 创建软链接
ln -s /data/pgsql/15/data /var/lib/pgsql/15/data

# 确保权限正确
chown -R postgres:postgres /var/lib/pgsql/15/data

5. 启动 PostgreSQL

启动方式和之前对应。如果用了 systemctl,之前停的服务现在直接启动即可。如果习惯手动操作,用 pg_ctlpostmaster 也一样。

# 使用 systemctl
systemctl start postgresql-15

# 或直接启动
/usr/pgsql-15/bin/postmaster -D "$NEW_DATA_DIR" &

# 或使用 pg_ctl
/usr/pgsql-15/bin/pg_ctl start -D "$NEW_DATA_DIR"

6. 验证

启动后别急着走,先确认一下数据目录是否真的指向了新路径。

# 检查数据目录
/usr/pgsql-15/bin/psql -h localhost -p 30004 -U postgres -c "SHOW data_directory;"

# 查看当前配置
/usr/pgsql-15/bin/psql -h localhost -p 30004 -U postgres -c "SELECT * FROM pg_settings WHERE name LIKE '%data_directory%';"

7. 更新 systemd 服务文件(如果使用 systemctl)

如果启动服务依赖 systemctl,且启动命令中没有显式指定 -D 参数,就需要在服务文件中更新 PGDATA 环境变量。否则重启后服务还是会去找原来的路径。

# 编辑服务文件
vi /etc/systemd/system/postgresql-15.service

# 或编辑 override 文件
mkdir -p /etc/systemd/system/postgresql-15.service.d
cat > /etc/systemd/system/postgresql-15.service.d/override.conf << EOF
[Service]
Environment=PGDATA=/data/pgsql/15/data
EOF

# 重新加载 systemd
systemctl daemon-reload

完整脚本示例

如果觉得手动一步步操作太麻烦,可以直接用下面的脚本。它把停止、迁移、配置、启动和验证串在了一起,省心不少。

#!/bin/bash
# 配置
OLD_DATA="/var/lib/pgsql/15/data"
NEW_DATA="/data/pgsql/15/data"
PG_VERSION="15"
PG_USER="postgres"

# 1. 停止 PostgreSQL
echo "停止 PostgreSQL..."
/usr/pgsql-15/bin/pg_ctl stop -D "$OLD_DATA" -m fast

# 2. 创建新目录
echo "创建新数据目录..."
mkdir -p "$NEW_DATA"
chown -R $PG_USER:$PG_USER "$NEW_DATA"
chmod 700 "$NEW_DATA"

# 3. 移动数据
echo "迁移数据文件..."
rsync -a v --progress "$OLD_DATA/" "$NEW_DATA/"

# 验证后可以删除原数据
# rm -rf "$OLD_DATA"

# 4. 更新配置
echo "更新配置文件..."
sed -i "s|data_directory = .*|data_directory = '$NEW_DATA'|" "$NEW_DATA/postgresql.conf"

# 5. 启动 PostgreSQL
echo "启动 PostgreSQL..."
/usr/pgsql-15/bin/pg_ctl start -D "$NEW_DATA"

# 6. 验证
echo "验证数据目录..."
/usr/pgsql-15/bin/psql -h localhost -p 30004 -U postgres -c "SHOW data_directory;"
echo "迁移完成!"

注意事项

有几个坑需要提前防住:

  1. 磁盘空间:迁移前先确认目标目录有足够空间,尤其是用复制操作时,原目录和新目录会同时存在,空间占用翻倍。
  2. 权限:数据目录必须属于 postgres 用户,权限为 700。这个检查一下就能避免很多启动问题。
  3. SELinux:如果系统开启了 SELinux,需要手动放行新的数据目录路径。
semanage fcontext -a -t postgresql_db_t "/data/pgsql(/.*)?"
restorecon -Rv /data/pgsql
  1. 防火墙:如果在新环境中改动了端口,别忘了更新防火墙规则。

检查当前数据目录

如果某天忘了数据目录到底在哪,可以用下面几种方式快速定位:

# 方法1:通过 SQL
/usr/pgsql-15/bin/psql -h localhost -p 30004 -U postgres -c "SHOW data_directory;"

# 方法2:查看进程
ps aux | grep postmaster | grep -E "-D"

# 方法3:查看配置文件
grep data_directory /var/lib/pgsql/15/data/postgresql.conf

以上就是更改 PostgreSQL 数据存储位置的完整流程。关键点无非是停服务、搬文件、改配置、启动验证,每一步都别跳,确保无误后再投入生产环境。

来源:https://www.jb51.net/database/366669xhn.htm
上一篇三台MySQL服务器Keepalived VIP高可用方案 下一篇MySQL面试调优:Explain、索引、慢查询及缓存架构
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
金仓数据库逻辑备份实战:全库导出与模式替换全流程
数据库 · 2026-07-03

金仓数据库逻辑备份实战:全库导出与模式替换全流程

在长期的运维实践中,我越来越体会到,备份就像一份保险——平时看似无用,但关键时刻却是唯一的救命稻草。逻辑备份看似简单,可真正执行恢复时,各种陷阱接连浮现:表名大小写不一致、Schema 未正确切换、Owner 属性未同步修改……任何一个环节处理不当,最终恢复出的数据库就会与预期相去甚远。 本文将深入

金仓数据库sys_rman物理备份全流程演练与误覆盖恢复
数据库 · 2026-07-03

金仓数据库sys_rman物理备份全流程演练与误覆盖恢复

干运维这行,逻辑备份和物理备份我都接触过,但说句实在话,真正能在生产环境里扛住事儿的,还得是物理备份。逻辑备份导出的是 SQL 语句,数据量一大,那速度慢得让人抓狂,而且最关键的是,它没法做时间点恢复。物理备份不一样,它直接拷贝数据文件,再配上 WAL 归档日志,想恢复到过去哪一秒都行,这是它最硬核

Windows下将MySQL注册为系统自启服务教程
数据库 · 2026-07-03

Windows下将MySQL注册为系统自启服务教程

先说一个关键前提:务必以管理员身份运行终端,否则 mysqld --install 这条命令几乎不可能成功。问题不在于命令写错,而是 Windows 系统的用户账户控制(UAC)机制会在中途拦截——在普通 CMD 或 PowerShell 窗口执行这条命令,要么直接提示 Access is deni

Mac版Navicat中快速对比两个数据库的表结构异同
数据库 · 2026-07-03

Mac版Navicat中快速对比两个数据库的表结构异同

直接说结论:Mac 版 Navicat 和 Windows 版在表结构比对逻辑上完全一致。但默认配置下,它确实无法承受“全库一键比对上万张表”的压力。要想避免卡死、内存溢出、进度条永远停在 0%,你必须手动将表分批处理,或者利用前缀过滤来控制扫描范围。 为什么 Mac 上点击「结构同步」后界面会卡住

MySQL中UNION操作推荐用UNION ALL的原因
数据库 · 2026-07-03

MySQL中UNION操作推荐用UNION ALL的原因

MySQL中UNION与UNION ALL性能对比:别再被“保险”迷惑,差距远超预期 先给出核心结论:UNION ALL 的性能通常比 UNION 高出不止一个数量级。原因在于,UNION 在合并结果集后会自动触发去重操作,这往往伴随着隐式排序,进而产生临时表和文件排序。而 UNION ALL 则直