PostgreSQL 15 – Move Data Directory

The Postgres data directory, sometimes known by the environment variable $PGDATA that references it is the heart of your database cluster installation. We as Database Administrators should never touch files within the data directory (with very few exceptions), as we could harm the integrity of the database software or completely destroy the database itself.

That being said, it may be that you’ve inherited an installation of Postgres or are otherwise tasked with moving this all-important directory to a different mount point or filesystem. Extreme care must be taken during these steps to ensure that you cause no harm. I’ve taken the below steps to successfully relocate a PostgreSQL 15 data directory on Red Hat Enterprise Linux, version 9.3. Before starting any of this, ensure that you have backups of the database, as well as the virtual machine or server itself if possible. This procedure could be different in your situation, always read the documentation for your version of PostgreSQL before attempting any operations such as these.

  • Connect to the database using the psql utility and show the location of both the data directory and the postgresql.conf file. This should be within the data directory, but it pays to be sure.
[postgres@dbtest ~]$ psql
psql (15.1)
Type "help" for help.

postgres=# show data_directory;
   data_directory   
--------------------
 /var/lib/pgsql/15/data
(1 row)

postgres=# show config_file;
            config_file             
------------------------------------
 /var/lib/pgsql/15/data/postgresql.conf
(1 row)
  • Shutdown the database.
[postgres@dbtest ~]$ sudo systemctl stop postgresql-15
[postgres@dbtest ~]$ sudo systemctl status postgresql-15
  • Make a copy of the data directory to revert to in case something goes wrong with the original.
[postgres@dbtest ~]$ cd /var/lib/pgsql/15
[postgres@dbtest /var/lib/pgsql/15]$ tar -cvf data_backup.tar ./data
[postgres@dbtest /var/lib/pgsql/15]$ gzip data_backup.tar
  • Create the directory that will hold the new data directory, change the user and group ownership to that of the operating system user that owns the PostgreSQL database software. By convention, this user is named: postgres.
[postgres@dbtest ~]$ sudo mkdir /postgresdata
[postgres@dbtest ~]$ sudo chown postgres:postgres /postgresdata
[postgres@dbtest ~]$ sudo chmod 700 /postgresdata
  • Use the rsync command to copy the existing data directory over to the new location.
[postgres@dbtest ~]$ rsync -av /var/lib/pgsql/15/data /postgresdata
  • In the copy of the data directory in the new location, edit file postgresql.conf to change the data_directory parameter to point to the full path of the new data directory.
[postgres@dbtest ~]$ vi /postgresdata/postgresql.conf
data_directory = '/postgresdata/data'
  • Next, edit the systemd service configuration file. Change the value of the line that shows Environment=PGDATA=/var/lib/pgsql/15/data to point to the new location.
[postgres@dbtest ~]$ sudo vi /lib/systemd/system/postgresql-15.service
Environment=PGDATA=/postgresdata/data
  • At this point, it’s a good time to halt any cron jobs that may reference the old $PGDATA environment variable. Also check that files .bashrc and .bash_profile do not contain any references to the old PGDATA directory. If they do, change them before restarting the database.
  • After making these changes, you should be able to restart the database using systemctl after reloading the systemd daemon so that it recognizes the changes that were made to file postgresql-15.service.
[postgres@dbtest ~]$ sudo systemctl daemon-reload
[postgres@dbtest ~]$ sudo systemctl start postgresql-15
[postgres@dbtest ~]$ sudo systemctl status postgresql-15
  • If all went well, PostgreSQL should now be running and making use of the new data_directory location. Double-check by executing the commands that we ran in the first part of this post. They should now show the new location.
[postgres@dbtest ~]$ psql
psql (15.1)
Type "help" for help.

postgres=# show data_directory;
   data_directory   
--------------------
 /postgresdata/data
(1 row)

postgres=# show config_file;
            config_file             
------------------------------------
 /postgresdata/data/postgresql.conf
(1 row)
  • At this point, you should take a backup of the database using your preferred method. Assuming that archive mode is enabled, you can take a full, hot backup using a utility such as pg_basebackup or by using a third-party backup solution.
  • Note that the same process can be followed (more or less) using the same steps for databases in a primary/standby relationship. One should first shut down both the primary and the standby databases, make the changes above, then bring both databases back up, starting with the primary. I’ve carried out these steps successfully on RHEL 9.3 with PostgreSQL 15.

Hope this helps,
Dustin

Leave a Reply

Your email address will not be published. Required fields are marked *