pg_dump y pg_restore son las herramientas oficiales de PostgreSQL para exportar una base de datos a un archivo y cargarla en otro servidor. Funcionan entre versiones distintas, así que también sirven para actualizar de versión mayor moviendo los datos a un servidor nuevo. En esta guía migrarás una base de datos desde un servidor de origen a un servidor de destino con Ubuntu 24.04, usando volcado y restauración en paralelo, y comprobarás que los datos han llegado completos.

Requisitos previos

  • Un servidor de origen con PostgreSQL y la base de datos a migrar. En los ejemplos se llama appdb y su propietario es el rol appuser.
  • Un servidor de destino con Ubuntu 24.04 LTS y PostgreSQL instalado, por ejemplo un VPS de CubePath. Su versión debe ser igual o superior a la del origen.
  • Un usuario no root con privilegios sudo en ambos servidores.
  • Espacio libre en disco en ambos servidores de al menos el tamaño de la base de datos (el volcado suele ocupar bastante menos gracias a la compresión).
  • Acceso SSH del servidor de origen al de destino para copiar el volcado.

Los comandos se ejecutan como el usuario de sistema postgres, que en Debian y Ubuntu puede conectarse a su servidor local sin contraseña.

Formatos de volcado

pg_dump admite cuatro formatos. Para migraciones, el formato directorio es la mejor opción porque es el único que permite volcar en paralelo y, como el formato custom, admite restauración paralela y selectiva.

FormatoOpciónSe restaura conVolcado paraleloRestauración paralela
SQL plano-FppsqlNoNo
Custom-Fcpg_restoreNoSí
Directorio-Fdpg_restoreSíSí
Tar-Ftpg_restoreNoNo

Paso 1: Comprobar las versiones

pg_dump puede leer servidores de versiones anteriores, pero no posteriores. Usa siempre el pg_dump de la versión del servidor de destino (o superior). Consulta la versión del servidor de origen:

sudo -u postgres psql -c "SELECT version();"
                                  version
---------------------------------------------------------------------------
 PostgreSQL 14.13 (Ubuntu 14.13-0ubuntu0.22.04.1) on x86_64-pc-linux-gnu ...

En el destino, Ubuntu 24.04 incluye PostgreSQL 16. Comprueba la versión de las herramientas cliente:

pg_dump --version
pg_dump (PostgreSQL) 16.10 (Ubuntu 16.10-0ubuntu0.24.04.1)

Si el destino tiene una versión más reciente que el origen (por ejemplo 14 en origen y 16 en destino), instala en el servidor de origen el cliente de la versión del destino desde el repositorio oficial de PostgreSQL (PGDG), así el volcado lo genera un pg_dump que entiende ambas versiones:

sudo apt install -y postgresql-common
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
sudo apt install -y postgresql-client-16

Cambia 16 por la versión mayor del destino. Para asegurarte de usar ese binario, en el paso 4 llama a pg_dump con su ruta completa, /usr/lib/postgresql/16/bin/pg_dump. Si ambos servidores tienen la misma versión, no necesitas nada de esto.

Paso 2: Revisar la base de datos de origen

Antes de migrar, anota el tamaño de la base de datos y el número de filas de las tablas principales para compararlos después:

sudo -u postgres psql -d appdb -c "SELECT pg_size_pretty(pg_database_size('appdb'));"
 pg_size_pretty
----------------
 12 GB

Revisa también las extensiones instaladas, ya que deben estar disponibles en el destino:

sudo -u postgres psql -d appdb -c "\dx"

Si aparece alguna extensión que no sea de las incluidas con PostgreSQL (por ejemplo postgis o timescaledb), instala su paquete en el servidor de destino antes de restaurar.

Paso 3: Exportar roles y objetos globales

pg_dump vuelca una sola base de datos y no incluye los roles ni sus contraseñas, que son globales al servidor. Expórtalos con pg_dumpall:

sudo -u postgres pg_dumpall --globals-only -f /var/lib/postgresql/globals.sql

El archivo contiene sentencias CREATE ROLE y ALTER ROLE. Ábrelo y elimina los roles que no quieras llevar al destino:

sudo -u postgres nano /var/lib/postgresql/globals.sql

Paso 4: Volcar la base de datos en paralelo

Crea el volcado en formato directorio con varios procesos. Usa como máximo tantos trabajos como núcleos tenga el servidor de origen, y ten en cuenta que cada trabajo abre una conexión adicional:

sudo -u postgres pg_dump \
  --format=directory \
  --jobs=4 \
  --verbose \
  --file=/var/lib/postgresql/appdb.dir \
  appdb

Al terminar, comprueba el tamaño del volcado y que su índice se lee sin errores:

sudo du -sh /var/lib/postgresql/appdb.dir
sudo -u postgres pg_restore --list /var/lib/postgresql/appdb.dir | head -n 15
3.1G	/var/lib/postgresql/appdb.dir
;
; Archive created at 2026-09-25 10:12:03 UTC
;     dbname: appdb
;     TOC Entries: 412
;     Compression: gzip
;     Dump Version: 1.15-0
;     Format: DIRECTORY
...

Paso 5: Copiar el volcado al servidor de destino

Copia el directorio y el archivo de roles al destino con rsync, sustituyendo your_user y your_server_ip:

sudo rsync -a --info=progress2 \
  /var/lib/postgresql/appdb.dir /var/lib/postgresql/globals.sql \
  your_user@your_server_ip:/tmp/

En el servidor de destino, mueve los archivos a un directorio del usuario postgres:

sudo mv /tmp/appdb.dir /tmp/globals.sql /var/lib/postgresql/
sudo chown -R postgres:postgres /var/lib/postgresql/appdb.dir /var/lib/postgresql/globals.sql

Paso 6: Restaurar roles y crear la base de datos

En el servidor de destino, carga los roles:

sudo -u postgres psql -f /var/lib/postgresql/globals.sql

Verás un error role "postgres" already exists, que es normal y se puede ignorar. Comprueba que el rol de la aplicación existe:

sudo -u postgres psql -c "\du appuser"

Crea la base de datos vacía con el mismo propietario que en el origen:

sudo -u postgres createdb --owner=appuser appdb

Paso 7: Restaurar en paralelo

Restaura el volcado con varios trabajos. Aquí conviene usar tantos como núcleos tenga el servidor de destino, porque la creación de índices se reparte entre ellos:

sudo -u postgres pg_restore \
  --dbname=appdb \
  --jobs=4 \
  --exit-on-error \
  --verbose \
  /var/lib/postgresql/appdb.dir

--exit-on-error detiene la restauración en el primer error en lugar de continuar y dejar una base de datos a medias sin que te enteres. Si el rol propietario no existe en el destino y no quieres crearlo, sustituye esta opción por --no-owner --role=appuser para que todo quede a nombre de appuser.

Al terminar, actualiza las estadísticas del planificador, que no se incluyen en el volcado:

sudo -u postgres vacuumdb --analyze-in-stages --dbname=appdb

Paso 8: Verificar la migración

Compara el tamaño y el número de filas con lo que anotaste en el paso 2. Para un conteo exacto en las tablas importantes, usa count(*) en ambos servidores:

sudo -u postgres psql -d appdb -c "SELECT count(*) FROM pedidos;"

Para una vista general de todas las tablas, esta consulta muestra el número de filas estimado tras el ANALYZE:

sudo -u postgres psql -d appdb -c "SELECT relname, n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC LIMIT 10;"
   relname    | n_live_tup
--------------+------------
 pedidos      |    4812330
 lineas       |    1920410
 clientes     |     210944
...

Comprueba por último que la aplicación puede conectarse con su usuario:

psql "host=127.0.0.1 dbname=appdb user=appuser" -c "SELECT current_user, current_database();"

Restaurar solo una parte del volcado

Un volcado en formato directorio o custom permite restaurar objetos concretos sin repetir la exportación.

Para restaurar una sola tabla con sus datos:

sudo -u postgres pg_restore --dbname=appdb --table=clientes /var/lib/postgresql/appdb.dir

Para un control fino, genera la lista de contenido, edítala comentando con ; las líneas que no quieras y restaura usando esa lista:

sudo -u postgres pg_restore --list /var/lib/postgresql/appdb.dir > /tmp/appdb.list
nano /tmp/appdb.list
sudo -u postgres pg_restore --dbname=appdb --use-list=/tmp/appdb.list /var/lib/postgresql/appdb.dir

Otras opciones útiles de pg_dump para volcados parciales son --schema-only (solo estructura), --data-only (solo datos), --schema=nombre y --exclude-table=nombre.

Solución de problemas

pg_dump: error: aborting because of server version mismatch. El pg_dump es más antiguo que el servidor. Instala el cliente de la versión correcta como en el paso 1.

FATAL: sorry, too many clients already durante el volcado. Cada trabajo de --jobs abre una conexión. Reduce el número de trabajos o aumenta max_connections en el origen.

ERROR: role "appuser" does not exist al restaurar. No cargaste los roles del paso 6. Cárgalos, o restaura con --no-owner --role=appuser.

ERROR: extension "postgis" is not available. Falta el paquete de la extensión en el destino. Instálalo (por ejemplo postgresql-16-postgis-3), borra la base de datos con dropdb appdb, vuelve a crearla y repite la restauración.

Conclusión

Has migrado una base de datos PostgreSQL entre servidores con un volcado en formato directorio, restaurado en paralelo junto con sus roles y verificado el resultado. El mismo procedimiento sirve para cambiar de versión mayor. Como siguientes pasos, puedes automatizar volcados periódicos con un temporizador de systemd, reducir la ventana de corte de futuras migraciones con replicación lógica (CREATE PUBLICATION y CREATE SUBSCRIPTION) o configurar copias continuas con archivado de WAL.