Skip to content

Instantly share code, notes, and snippets.

@hartleybrody
Last active December 1, 2021 13:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hartleybrody/b0975ef3450995db58b247e1f5859a2d to your computer and use it in GitHub Desktop.
Save hartleybrody/b0975ef3450995db58b247e1f5859a2d to your computer and use it in GitHub Desktop.
upgrading postgres

Postgres is usually run automatically on my laptop. I also have a weekly cronjob that does brew update and brew upgrade which sometimes bumps the version of portgres that I'm running. Newer versions of the postgres server software aren't necessarily compatible with the older version's data directory structure, and so you need to "upgrade" your database to see all of your old data in the upgraded postgres server.

Trying to start the database manually with

pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start

Which gives an error message and tells me where to look (note that I passed in the log directory when I ran the command)

waiting for server to start.... stopped waiting
pg_ctl: could not start server
Examine the log output.

If I examine that logfile

tail -f /usr/local/var/postgres/server.log

the last few lines say:

2017-11-14 23:43:31.218 +07 [13654] FATAL:  database files are incompatible with server
2017-11-14 23:43:31.218 +07 [13654] DETAIL:  The data directory was initialized by PostgreSQL version 9.6, which is not compatible with this version 10.1.

Time to upgrade

Takes a few steps. Basically, we're going to move our "old" data directory out of the way, and then create a new data directory with the latest version of the postgres server software. Finally, we'll use pg_upgrade to import our old data into the new postgres server data directory format, and then do a bit of cleanup.

You'll need to ensure that the new database isn't currently running

brew services stop postgresql

Move the old data directory to a backup directory

mv /usr/local/var/postgres /usr/local/var/postgres.backup

Create a new data directory, using the latest version of the software

initdb -D /usr/local/var/postgres

Now you have a new database setup with the latest version of the postgres server software, but your old data isn't in it yet. For that, we'll use the pg_upgrade command:

pg_upgrade \
    -b /usr/local/Cellar/postgresql/9.6.1/bin \
    -B /usr/local/Cellar/postgresql/10.1/bin \
    -d /usr/local/var/postgres.backup \
    -D /usr/local/var/postgres

Note that you'll need to tell that upgrade command which binary versions you are upgrading from and to. So where it says 9.6.1 and 10.1, you'll need to change the path to point to the old and new versions of postgres, which you should see in the error log message, above:

The data directory was initialized by PostgreSQL version {old}, which is not compatible with this version {new}.

As this runs, you should see a bunch of tests running and passing

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 reg* data types in user tables                 ok
Checking for contrib/isn with bigint-passing mismatch       ok
Checking for invalid "unknown" user columns                 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

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

Performing Upgrade
------------------
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_clog to new server                           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 analyze new cluster                      ok
Creating script to delete old cluster                       ok
Checking for hash indexes                                   ok

Upgrade Complete
----------------
Optimizer statistics are not transferred by pg_upgrade so,
once you start the new server, consider running:
    ./analyze_new_cluster.sh

Running this script will delete the old cluster's data files:
    ./delete_old_cluster.sh

It creates two scripts in your current working directory, both of which you should consider running afterwards:

./analyze_new_cluster.sh

Will help optimize your new database and then you can run:

./delete_old_cluster.sh

to remove the old data directory we made.

You can remove those two auto-generated scripts.

rm analyze_new_cluster.sh
rm delete_old_cluster.sh

Finally, use brew to start your new database back up again.

brew services start postgresql

Voila! Enjoy your shiny new database server with all of your old data still intact :)

Edit (Jan 9, 2019): I also found this tutorial which has a great walk through of how to upgrade as well.

@hartleybrody
Copy link
Author

This tutorial and commands saved my butt again.

@hartleybrody
Copy link
Author

When you're done upgrading, don't forget to update the database's timezone to UTC:

show timezone; (via SO)

SET TIME ZONE 'UTC' (via SO)

@hartleybrody
Copy link
Author

hartleybrody commented Dec 1, 2021

If you run into an error while upgrading that says

The source cluster was not shut down cleanly.
Failure, exiting

You can simply restart the previous/old version of postgres using the data directory you backed up, with

/path/to/old_postgres_version/bin/postgres -D /usr/local/var/postgres.backup

You may see some log messages as the old DB version attempts to fix the issues. Then once it is running successfully, kill it with Ctrl-C and it should do a graceful shutdown and put your data directory in a good state so you can continue running the pg_upgrade command.

via https://www.philihp.com/2019/postgres-10-11-upgrade.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment