Copiar base de datos

Copiar una base de datos es una tarea frecuente: crear un entorno de pruebas a partir de producción, clonar datos para un desarrollador, o migrar una base de datos entre servidores. MySQL no tiene un comando COPY DATABASE ni RENAME DATABASE integrado, pero combinando mysqldump con mysql puedes lograr exactamente lo mismo de forma fiable.

Copiar en el mismo servidor

Para crear una copia de una base de datos dentro del mismo servidor, el proceso consiste en crear la base de datos destino y luego volcar los datos directamente usando un pipe:

# Crear la base de datos destino
mysql -u root -p -e "CREATE DATABASE tienda_staging CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
 
# Copiar estructura y datos
mysqldump --single-transaction --routines --triggers --events \
    -u root -p tienda_mysql | mysql -u root -p tienda_staging

Este comando usa mysqldump para leer la base de datos original y envía la salida directamente al cliente mysql que la escribe en la base de datos destino. No se crea ningún archivo intermedio en disco, lo que ahorra espacio y tiempo.

Si prefieres usar un archivo intermedio para verificar antes de restaurar:

# Exportar
mysqldump --single-transaction --routines --triggers --events \
    -u root -p tienda_mysql > /tmp/tienda_mysql_copia.sql
 
# Importar en la nueva base de datos
mysql -u root -p tienda_staging < /tmp/tienda_mysql_copia.sql
 
# Limpiar el archivo temporal
rm /tmp/tienda_mysql_copia.sql

Copiar entre servidores

Para copiar una base de datos de un servidor a otro, combina mysqldump en el servidor origen con mysql apuntando al servidor destino:

# Directo con pipe a través de la red
mysqldump --single-transaction --routines --triggers --events \
    -h servidor_origen -u admin -p tienda_mysql \
    | mysql -h servidor_destino -u admin -p tienda_mysql

Si los servidores no tienen conectividad directa entre sí, usa SSH como intermediario:

# A través de SSH
mysqldump --single-transaction --routines --triggers --events \
    -u root -p tienda_mysql \
    | ssh usuario@servidor_destino "mysql -u admin -p tienda_mysql"

Para bases de datos grandes, comprimir en tránsito reduce significativamente el tiempo de transferencia:

# Comprimido en tránsito
mysqldump --single-transaction --routines --triggers --events \
    -u root -p tienda_mysql \
    | gzip | ssh usuario@servidor_destino "gunzip | mysql -u admin -p tienda_mysql"

Renombrar una base de datos

MySQL eliminó el comando RENAME DATABASE en la versión 5.1 porque podía causar pérdida de datos en ciertos escenarios. La forma segura de "renombrar" es copiar y luego eliminar la original:

# Paso 1: Crear la nueva base de datos
mysql -u root -p -e "CREATE DATABASE tienda_nueva CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
 
# Paso 2: Copiar todo
mysqldump --single-transaction --routines --triggers --events \
    -u root -p tienda_antigua | mysql -u root -p tienda_nueva
 
# Paso 3: Verificar que la copia es correcta
mysql -u root -p -e "
SELECT 'tienda_antigua' AS origen, COUNT(*) AS tablas FROM information_schema.tables WHERE table_schema = 'tienda_antigua'
UNION ALL
SELECT 'tienda_nueva', COUNT(*) FROM information_schema.tables WHERE table_schema = 'tienda_nueva';
"
 
# Paso 4: Solo si la verificación es correcta, eliminar la original
mysql -u root -p -e "DROP DATABASE tienda_antigua"

Copiar solo la estructura

Si necesitas una copia vacía de la base de datos, usa --no-data:

mysql -u root -p -e "CREATE DATABASE tienda_test"
 
mysqldump --no-data --routines --triggers --events \
    -u root -p tienda_mysql | mysql -u root -p tienda_test

La base de datos tienda_test tendrá todas las tablas, índices, foreign keys, procedimientos almacenados y triggers, pero sin datos.

Copiar estructura y datos parciales

Puedes copiar la estructura completa y luego agregar datos solo de algunas tablas o con filtros:

# Primero la estructura completa
mysqldump --no-data --routines --triggers --events \
    -u root -p tienda_mysql | mysql -u root -p tienda_staging
 
# Luego datos de tablas de catálogo (pequeñas)
mysqldump --no-create-info -u root -p tienda_mysql \
    categorias marcas proveedores | mysql -u root -p tienda_staging
 
# Datos parciales de tablas grandes
mysqldump --no-create-info -u root -p tienda_mysql \
    pedidos --where="fecha_pedido >= '2026-01-01'" | mysql -u root -p tienda_staging

Verificar la copia

Después de copiar, verifica que ambas bases de datos son consistentes:

-- Comparar número de tablas
SELECT
    table_schema AS base_datos,
    COUNT(*) AS total_tablas,
    SUM(table_rows) AS total_filas_aprox
FROM information_schema.tables
WHERE table_schema IN ('tienda_mysql', 'tienda_staging')
GROUP BY table_schema;
base_datostotal_tablastotal_filas_aprox
tienda_mysql15102450
tienda_staging15102450
-- Comparar tabla por tabla
SELECT
    t1.table_name,
    t1.table_rows AS filas_origen,
    t2.table_rows AS filas_destino
FROM information_schema.tables t1
JOIN information_schema.tables t2
    ON t1.table_name = t2.table_name
WHERE t1.table_schema = 'tienda_mysql'
AND t2.table_schema = 'tienda_staging'
ORDER BY t1.table_name;
table_namefilas_origenfilas_destino
categorias1515
clientes52305230
detalle_pedidos6732067320
pedidos2845028450
productos150150

Los valores de table_rows en information_schema son aproximados para InnoDB, pero para una verificación rápida son suficientes. Si necesitas conteos exactos, ejecuta SELECT COUNT(*) en cada tabla.

Script automatizado de copia

Un script completo que copia una base de datos con verificación:

#!/bin/bash
# /scripts/copiar-base-datos.sh
 
ORIGEN=$1
DESTINO=$2
CONF="/root/.my.cnf"
 
if [ -z "$ORIGEN" ] || [ -z "$DESTINO" ]; then
    echo "Uso: $0 <base_origen> <base_destino>"
    exit 1
fi
 
echo "Copiando ${ORIGEN} -> ${DESTINO}..."
 
# Crear base de datos destino
mysql --defaults-file=$CONF -e "CREATE DATABASE IF NOT EXISTS \`${DESTINO}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
 
# Copiar
mysqldump --single-transaction --routines --triggers --events \
    --defaults-file=$CONF "${ORIGEN}" | mysql --defaults-file=$CONF "${DESTINO}"
 
if [ $? -eq 0 ]; then
    echo "Copia completada exitosamente."
 
    # Verificar
    TABLAS_ORIGEN=$(mysql --defaults-file=$CONF -sN -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='${ORIGEN}'")
    TABLAS_DESTINO=$(mysql --defaults-file=$CONF -sN -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='${DESTINO}'")
 
    echo "Tablas en ${ORIGEN}: ${TABLAS_ORIGEN}"
    echo "Tablas en ${DESTINO}: ${TABLAS_DESTINO}"
else
    echo "ERROR: La copia falló" >&2
    exit 1
fi
chmod +x /scripts/copiar-base-datos.sh
/scripts/copiar-base-datos.sh tienda_mysql tienda_staging

Copiar bases de datos es una operación rutinaria en la administración de MySQL. Aunque no existe un comando nativo, la combinación de mysqldump y mysql es fiable, flexible y funciona tanto dentro del mismo servidor como entre servidores diferentes.

Escrito por Eduardo Lázaro