Backup de todas las bases de datos

Cuando administras un servidor MySQL con múltiples bases de datos, necesitas una forma de respaldarlas todas con un solo comando. La opción --all-databases de mysqldump exporta cada base de datos del servidor en un único archivo, incluyendo las sentencias CREATE DATABASE y USE necesarias para recrear todo el entorno.

Backup completo del servidor

La forma más directa de respaldar todo el servidor es:

mysqldump --all-databases -u root -p > servidor_completo.sql

Este comando exporta todas las bases de datos, incluyendo las bases de datos del sistema como mysql, sys, performance_schema e information_schema. El archivo resultante contiene las sentencias necesarias para recrear completamente el servidor desde cero.

Para un backup de producción robusto, combina las opciones esenciales:

mysqldump \
    --all-databases \
    --single-transaction \
    --routines \
    --triggers \
    --events \
    -u root -p | gzip > /backups/servidor_$(date +%Y%m%d_%H%M%S).sql.gz

Contenido del archivo de backup

El archivo generado con --all-databases tiene una estructura que procesa cada base de datos secuencialmente:

-- MySQL dump 10.13  Distrib 8.4.0, for Linux (x86_64)
 
--
-- Current Database: `mysql`
--
 
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysql`;
USE `mysql`;
-- sentencias CREATE TABLE e INSERT para tablas del sistema...
 
--
-- Current Database: `tienda_mysql`
--
 
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `tienda_mysql`;
USE `tienda_mysql`;
-- sentencias CREATE TABLE e INSERT para tienda_mysql...
 
--
-- Current Database: `inventario_app`
--
 
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `inventario_app`;
USE `inventario_app`;
-- sentencias para inventario_app...

Cada base de datos está claramente delimitada con comentarios, lo que facilita identificar dónde comienza y termina el respaldo de cada una.

Excluir bases de datos del sistema

En muchos casos no necesitas respaldar las bases de datos del sistema (mysql, sys, performance_schema, information_schema), especialmente si estás restaurando en un servidor que ya tiene MySQL instalado. Desafortunadamente, mysqldump no tiene una opción --exclude-databases, pero puedes lograr el mismo efecto usando --databases con la lista de bases que sí quieres respaldar:

# Obtener la lista de bases de datos excluyendo las del sistema
mysql -u root -p -e "SHOW DATABASES" | grep -Ev "^(Database|mysql|sys|performance_schema|information_schema)$"
tienda_mysql
inventario_app
logs_sistema
analytics
# Respaldar solo las bases de datos de aplicación
mysqldump \
    --single-transaction \
    --routines \
    --triggers \
    --events \
    --databases tienda_mysql inventario_app logs_sistema analytics \
    -u root -p | gzip > /backups/apps_$(date +%Y%m%d).sql.gz

Automatizar la exclusión

Puedes automatizar la selección de bases de datos en un script:

#!/bin/bash
# /scripts/backup-all-app-dbs.sh
 
EXCLUIR="mysql|sys|performance_schema|information_schema"
BACKUP_DIR="/backups/mysql"
FECHA=$(date +%Y%m%d_%H%M%S)
 
# Obtener lista de bases de datos de aplicación
DATABASES=$(mysql --defaults-file=/root/.my.cnf -e "SHOW DATABASES" -s --skip-column-names \
    | grep -Ev "^(${EXCLUIR})$" \
    | tr '\n' ' ')
 
echo "Respaldando bases de datos: ${DATABASES}"
 
mysqldump \
    --single-transaction \
    --routines \
    --triggers \
    --events \
    --defaults-file=/root/.my.cnf \
    --databases ${DATABASES} | gzip > "${BACKUP_DIR}/todas_apps_${FECHA}.sql.gz"
 
if [ $? -eq 0 ]; then
    echo "[$(date)] Backup completado exitosamente"
    ls -lh "${BACKUP_DIR}/todas_apps_${FECHA}.sql.gz"
else
    echo "[$(date)] ERROR: El backup falló" >&2
    exit 1
fi

Backup de múltiples bases de datos específicas

La opción --databases permite especificar exactamente cuáles bases de datos respaldar:

mysqldump \
    --single-transaction \
    --routines \
    --triggers \
    --databases tienda_mysql inventario_app \
    -u root -p > apps_produccion.sql

A diferencia de pasar un solo nombre de base de datos como argumento posicional, --databases incluye las sentencias CREATE DATABASE y USE en el archivo, lo que hace la restauración más autónoma.

Backups individuales por base de datos

En lugar de un único archivo gigante, una estrategia alternativa es crear un archivo separado para cada base de datos. Esto facilita restaurar bases de datos individuales sin tener que extraer porciones del archivo completo:

#!/bin/bash
# /scripts/backup-individual.sh
 
BACKUP_DIR="/backups/mysql/individuales"
FECHA=$(date +%Y%m%d)
EXCLUIR="mysql|sys|performance_schema|information_schema"
 
mkdir -p "${BACKUP_DIR}/${FECHA}"
 
# Respaldar cada base de datos por separado
for DB in $(mysql --defaults-file=/root/.my.cnf -e "SHOW DATABASES" -s --skip-column-names \
    | grep -Ev "^(${EXCLUIR})$"); do
 
    echo "Respaldando ${DB}..."
 
    mysqldump \
        --single-transaction \
        --routines \
        --triggers \
        --events \
        --defaults-file=/root/.my.cnf \
        --databases "${DB}" | gzip > "${BACKUP_DIR}/${FECHA}/${DB}.sql.gz"
 
    if [ $? -eq 0 ]; then
        TAMANO=$(ls -lh "${BACKUP_DIR}/${FECHA}/${DB}.sql.gz" | awk '{print $5}')
        echo "  OK (${TAMANO})"
    else
        echo "  ERROR al respaldar ${DB}" >&2
    fi
done
 
echo "Backups completados en ${BACKUP_DIR}/${FECHA}/"
ls -lh "${BACKUP_DIR}/${FECHA}/"

La salida sería algo así:

Respaldando tienda_mysql...
  OK (1.2G)
Respaldando inventario_app...
  OK (450M)
Respaldando logs_sistema...
  OK (2.8G)
Respaldando analytics...
  OK (890M)
Backups completados en /backups/mysql/individuales/20260214/

Rotación de backups

Cuando haces backup de todas las bases de datos, los archivos pueden ser considerablemente grandes. Implementa una política de rotación para evitar llenar el disco:

#!/bin/bash
# Rotación de backups
BACKUP_DIR="/backups/mysql"
 
# Mantener los últimos 7 backups diarios
find ${BACKUP_DIR} -name "todas_apps_*.sql.gz" -mtime +7 -delete
 
# Mantener los últimos 4 backups semanales (los del domingo)
find ${BACKUP_DIR}/semanales -name "*.sql.gz" -mtime +28 -delete
 
# Mantener los últimos 12 backups mensuales
find ${BACKUP_DIR}/mensuales -name "*.sql.gz" -mtime +365 -delete

Respaldar incluyendo la base mysql

La base de datos mysql contiene las cuentas de usuario, permisos, y otras configuraciones del servidor. Si necesitas restaurar el servidor completo, incluyendo los usuarios y sus privilegios, necesitas incluirla:

# Backup completo incluyendo usuarios y permisos
mysqldump --all-databases --single-transaction \
    --routines --triggers --events \
    -u root -p > servidor_completo_con_usuarios.sql

Alternativamente, puedes respaldar solo las cuentas de usuario con --no-create-db --no-data sobre la base mysql:

# Solo estructura de usuarios (sin datos de tablas del sistema)
mysql -u root -p -e "SHOW GRANTS FOR 'app_user'@'localhost'"

Monitorear el progreso

Para backups grandes que tardan mucho, puedes monitorear el progreso usando pv (pipe viewer):

# Instalar pv si no lo tienes
sudo apt install pv
 
# Backup con indicador de progreso
mysqldump --all-databases --single-transaction \
    --routines --triggers --events \
    -u root -p | pv | gzip > /backups/servidor_completo.sql.gz

pv muestra la cantidad de datos transferidos, la velocidad y el tiempo transcurrido. No puede mostrar un porcentaje de progreso porque no conoce el tamaño total de antemano, pero la velocidad te da una buena idea de cuánto falta.

Restaurar el backup completo

Para restaurar todas las bases de datos desde un backup completo:

# Desde archivo sin comprimir
mysql -u root -p < servidor_completo.sql
 
# Desde archivo comprimido con gzip
zcat /backups/servidor_completo.sql.gz | mysql -u root -p

Si solo necesitas restaurar una base de datos específica del archivo completo, puedes usar sed para extraer la sección correspondiente, pero es mucho más práctico tener backups individuales por base de datos para este propósito.

El backup completo del servidor es la base de cualquier estrategia de recuperación ante desastres. Combínalo con binary logs para lograr recuperación point-in-time y tendrás una protección robusta contra cualquier tipo de pérdida de datos. En el siguiente artículo veremos cómo exportar tablas individuales.

Escrito por Eduardo Lázaro