--- title: "Cómo migrar PostgreSQL con pg_dump y pg_restore" description: "Migra una base de datos PostgreSQL a otro servidor con pg_dump y pg_restore: roles globales, volcado paralelo en formato directorio, restauración y validación." category: "Operaciones de Base de Datos" language: es source: https://cubepath.com/es/docs/operaciones-de-base-de-datos/migracion-de-base-de-datos-pg-dump-pg-restore updated: 2026-09-25 --- # Cómo migrar PostgreSQL con pg_dump y pg_restore `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. | Formato | Opción | Se restaura con | Volcado paralelo | Restauración paralela | |---------|--------|-----------------|------------------|-----------------------| | SQL plano | `-Fp` | `psql` | No | No | | Custom | `-Fc` | `pg_restore` | No | Sí | | Directorio | `-Fd` | `pg_restore` | Sí | Sí | | Tar | `-Ft` | `pg_restore` | No | No | ## 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: ```bash sudo -u postgres psql -c "SELECT version();" ``` ```output 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: ```bash pg_dump --version ``` ```output 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: ```bash 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: ```bash sudo -u postgres psql -d appdb -c "SELECT pg_size_pretty(pg_database_size('appdb'));" ``` ```output pg_size_pretty ---------------- 12 GB ``` Revisa también las extensiones instaladas, ya que deben estar disponibles en el destino: ```bash 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`: ```bash 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: ```bash sudo -u postgres nano /var/lib/postgresql/globals.sql ``` > Nota: si el servidor de origen es un servicio gestionado sin acceso de superusuario, añade `--no-role-passwords` y define las contraseñas a mano en el destino. ## 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: ```bash 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: ```bash sudo du -sh /var/lib/postgresql/appdb.dir sudo -u postgres pg_restore --list /var/lib/postgresql/appdb.dir | head -n 15 ``` ```output 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 ... ``` > Consejo: el volcado es una fotografía consistente del momento en que empieza, pero los cambios que se hagan después no se incluyen. Para una migración definitiva, detén las escrituras de la aplicación antes de este paso. ## 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`: ```bash 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`: ```bash 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: ```bash 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: ```bash sudo -u postgres psql -c "\du appuser" ``` Crea la base de datos vacía con el mismo propietario que en el origen: ```bash 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: ```bash 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: ```bash 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: ```bash 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`: ```bash 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;" ``` ```output relname | n_live_tup --------------+------------ pedidos | 4812330 lineas | 1920410 clientes | 210944 ... ``` Comprueba por último que la aplicación puede conectarse con su usuario: ```bash 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: ```bash 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: ```bash 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.