PostgreSQL on OpenBSD: Upgrade 15 to 16 with pg_upgrade


Summary

OpenBSD gives us good documentation as a series of the project. (For example, the man pages are cared and kept maintained.) It’s applied to principal service packages as well as the OS. So is as to PostgreSQL.

Well, according to their pkg-readme on PostgreSQL (/usr/local/share/doc/pkg-readmes/postgresql-server), they suggest we have two ways to upgrade the database:

  1. pg_dumpall
  2. pg_upgrade

The former is slower so is not suitable for big databases, but doesn’t require the additional package. The latter is vice versa. This post is about the latter.

Environment

  • OS: OpenBSD 7.5 (upgraded from 7.4)
  • DB: PostgreSQL 16 (upgraded from 15)

Tutorial

Backup (Optional)

When you worry about backup, pg_dumpall is available:

$ pg_dumpall -U postgres > pg.sqldump

You may be asked by the superuser’s password at the number of the existing databases. The result was:

$ ls -lh pg.sqldump
-rw-r--r--  1 myuser    myuser    31.1M Aug 11 16:10 pg.sqldump

OS upgrade (optional)

The reason why upgrading PostgreSQL 15 to 16 should be required is up to the situation.

The situation of this post is to upgrade OpenBSD 7.4 to 7.5 which requires it. It is supposed running sysupgrade, sysmerge, syspatch and pkg_add -u are done. This post might be useful.

Here, running pkg_add -u asked like below:

$ pkg_add -u
(...)
postgresql-client-15.6->16.3 forward dependencies:
| Dependency of postgresql-server-15.6 on postgresql-client-=15.6 doesn't match
| Dependency of postgresql-contrib-15.6 on postgresql-client-=15.6 doesn't match
Merging postgresql-server-15.6->16.3 (ok)
Merging postgresql-contrib-15.6->16.3 (ok)
postgresql-server-16.3: Updating across a major version - data migration needed, see the pkg-readme.
Do you want to update now ? [y/N/a] y

Enter “y” as above. The result was below:

postgresql-client+postgresql-contrib+postgresql-server-15.6->16.3: ok
.libs1-postgresql-previous-13.5p0+postgresql-previous-14.6p0->postgresql-previous-15.4: ok
(...)
New and changed readme(s):
	/usr/local/share/doc/pkg-readmes/postgresql-server

Install pg_upgrade

The Ports package system helps:

$ doas pkg_add postgresql-pg_upgrade
quirks-7.14 signed on 2024-08-09T15:02:27Z
postgresql-pg_upgrade-16.3: ok

Stop the daemon

Stopping the server:

$ doas rcctl stop postgresql
postgresql(ok)

Now we are ready. Let’s upgrade the database !!

Create cluster of upgraded PostgreSQL

Prepare for creating the data directory. Move the current:

$ doas mv /var/postgresql/data /var/postgresql/data-15

Then mkdir it and initdb for PostgreSQL:

$ # doas su _postgresql -c "mkdir /var/postgresql/data && cd /var/postgresql && \
        initdb -D /var/postgresql/data -U postgres -A scram-sha-256 -E UTF8 -W"
$ doas su _postgresql -c "mkdir /var/postgresql/data && cd /var/postgresql && \
      initdb -D /var/postgresql/data -U postgres -A scram-sha-256 -E UTF8 --locale=ja_JP.UTF-8 -W"

The former above is due to the pkg-readme, and the latter is specific for my case, in which --locale=(...) option is added.

The result was:

The files belonging to this database system will be owned by user "_postgresql".
This user must also own the server process.

The database cluster will be initialized with locale "ja_JP.UTF-8".
initdb: could not find suitable text search configuration for locale "ja_JP.UTF-8"
The default text search configuration will be set to "simple".

Data page checksums are disabled.

Enter new superuser password: 
Enter it again:

Enter the password of your PostgreSQL superuser twice. Then it will be followed by the below:

fixing permissions on existing directory /var/postgresql/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 20
selecting default shared_buffers ... 128MB
selecting default time zone ... Asia/Tokyo
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

Success. You can now start the database server using:

    rcctl start postgresql

To start the PostgreSQL server automatically at boot:

    rcctl enable postgresql

Yay. The database is initiated with them generated.

Configure for migration

The steps here are temporary for the data migration.

Edit pg_hba.conf of the current (and also the next):

$ doas nvim /var/postgresql/data-15/pg_hba.conf

in order to allow local connection by the superuser:

  # TYPE  DATABASE        USER            ADDRESS                 METHOD
+ local all postgres trust

Note that you should put the line at the top in order to let it be the most highly prioritized.

Then copy the files below to the data directory, which includes pg_hba.conf. They are used by the upgraded software:

$ doas cp -p /var/postgresql/data-15/pg_hba.conf /var/postgresql/data/

$ # in addition, in case that tls is used:
$ doas cp -p /var/postgresql/data-15/server.{crt,key} /var/postgresql/data/

Run pg_upgrade

OK. Your database is now waiting for the upgrade. Run the command lines:

$ doas su _postgresql -c "cd /var/postgresql && \
      pg_upgrade -b /usr/local/bin/postgresql-15/ -B /usr/local/bin \
      -U postgres -d /var/postgresql/data-15/ -D /var/postgresql/data"

Besides, if you meet the error saying “connection to server on socket “/var/postgresql/.s.PGSQL.(…)” failed: fe_sendauth: no password supplied”, either .pgpass or PGPASSWORD environment variable might be helpful.

The result was below:

Performing Consistency Checks
-----------------------------
Checking cluster versions                                     ok
Checking database user is the install user                    ok
Checking database connection settings                         ok
Checking for prepared transactions                            ok
Checking for system-defined composite types in user tables    ok
Checking for reg* data types in user tables                   ok
Checking for contrib/isn with bigint-passing mismatch         ok
Checking for incompatible "aclitem" data type in user tables  ok
Creating dump of global objects                               ok
Creating dump of database schemas                             
                                                              ok
Checking for presence of required libraries                   ok
Checking database user is the install user                    ok
Checking for prepared transactions                            ok
Checking for new cluster tablespace directories               ok

If pg_upgrade fails after this point, you must re-initdb the
new cluster before continuing.

Performing Upgrade
------------------
Setting locale and encoding for new cluster                   ok
Analyzing all rows in the new cluster                         ok
Freezing all rows in the new cluster                          ok
Deleting files from new pg_xact                               ok
Copying old pg_xact to new server                             ok
Setting oldest XID for new cluster                            ok
Setting next transaction ID and epoch for new cluster         ok
Deleting files from new pg_multixact/offsets                  ok
Copying old pg_multixact/offsets to new server                ok
Deleting files from new pg_multixact/members                  ok
Copying old pg_multixact/members to new server                ok
Setting next multixact ID and offset for new cluster          ok
Resetting WAL archives                                        ok
Setting frozenxid and minmxid counters in new cluster         ok
Restoring global objects in the new cluster                   ok
Restoring database schemas in the new cluster                 
                                                              ok
Copying user relation files                                   
                                                              ok
Setting next OID for new cluster                              ok
Sync data directory to disk                                   ok
Creating script to delete old cluster                         ok
Checking for extension updates                                ok

Upgrade Complete
----------------
Optimizer statistics are not transferred by pg_upgrade.
Once you start the new server, consider running:
    /usr/local/bin/vacuumdb -U postgres --all --analyze-in-stages
Running this script will delete the old cluster's data files:
    ./delete_old_cluster.sh

Successful.

Restore configuration

Restore the configuration by removing the temporary line:

$ doas nvim /var/postgresql/data/pg_hba.conf

$ # in addition, if you care about restoring the previous one:
$ doas nvim /var/postgresql/data-15/pg_hba.conf

like below:

  # TYPE  DATABASE        USER            ADDRESS                 METHOD
- local all postgres trust

Configure for the new PostgreSQL (Optional)

When you have specific configuration with postgresql.conf etc., apply them:

$ # create the backup (optional):
$ doas cp -p /var/postgresql/data/postgresql.conf /var/postgresql/data/postgresql.conf.org

$ doas nvim /var/postgresql/data/postgresql.conf

like below (for example):

  (...)
+ listen_addresses = '*'
  (...)
+ ssl = on
  (...)

Besides, the original of postgresql.conf is placed as /usr/local/share/postgresql/postgresql.conf.sample.

Start the daemon again

All on the upgrade have been done. Let’s start the database server:

$ doas rcctl start postgresql

I hope the result is successful :)

Remove the package (Optional)

You are now free to farewell with appreciation to the package which worked fine:

$ doas pkg_delete postgresql-pg_upgrade
postgresql-pg_upgrade-16.3: ok

Conclusion

Through the steps above, we can upgrade PostgreSQL 15 to 16 with upgrading OpenBSD 7.4 to 7.5.

Besides, the data-15 directory may become “old” one in some future.

Wish you pretty happy time with the latest PostgreSQL on the latest OpenBSD 🌟


Comments or feedbacks are welcomed and appreciated.