Today I learned how to restore a single Postgres database from a global dump
generated with pg_dumpall
. Now, pg_dumpall
is handy when you want to back
up an entire Postgres cluster. It will dump all databases and global objects in
a single text file. In contrast, pg_dump
, the go-to tool for Postgres
backups, offers more control but only works with a single database and doesn’t
dump global objects, such as the roles/users linked to the database.
The problem with pg_dumpall
comes when you want to restore just one database
from the dump file. That’s not supported out of the box, but it is achievable
with some tinkering.
The pg_dumpall
dump is a plain text file that contains all the SQL commands
needed to restore the cluster. All database instructions are there as well; we
only need to extract them. Say we have one “mydb” database that we need to
retrieve. Open the dump file and look for a string starting with “connect
mydb”. That’s where our database instructions begin. Then look for the first
occurrence of “PostgreSQL database dump complete”. That’s where the
instructions end. This script, which I have to say makes clever use of sed
,
will do just that for us:
#!/bin/bash
[ $# -lt 2 ] && { echo "Usage: $0 <postgresql dump> <dbname>"; exit 1; }
sed "/connect.*$2/,\$!d" $1 | sed "/PostgreSQL database dump complete/,\$d"
The output will be to STDOUT; we want to pipe it into a file. If we named the
script pg_extract.sh
, as I did, we’d do:
./pg_extract.sh dumpall.sql mydb >> mydb.dump
Now we have the specific DB dump, and we can restore it like this:
psql (connection options) mydb < mydb.dump
If the database still exists on the cluster, we first want to drop it, or we’ll only get error messages:
psql (connection options) -d postgres -c "DROP DATABASE IF EXISTS mydb"
psql (connection options) -d postgres -c "CREATE DATABASE mydb"
DROP DATABASE
will fail if there are active connections. Either
force-drop all active connections or tell your peers to leave the database
alone. Merging the above passages in a script is an option.