Backup de una base de datos

El escenario más común de respaldo es exportar una base de datos completa con todas sus tablas, datos, procedimientos almacenados y demás objetos. Con mysqldump puedes crear un archivo SQL que contiene todo lo necesario para recrear esa base de datos exactamente como estaba en el momento del respaldo.

Backup básico

La forma más directa de respaldar una base de datos es pasar su nombre como argumento a mysqldump:

mysqldump -u root -p tienda_mysql > tienda_mysql_backup.sql

Este comando genera un archivo tienda_mysql_backup.sql que contiene las sentencias CREATE TABLE e INSERT para todas las tablas de la base de datos tienda_mysql. Sin embargo, esta forma básica tiene una limitación importante: no incluye la sentencia CREATE DATABASE, lo que significa que al restaurar necesitarás crear la base de datos manualmente antes de importar.

Backup con CREATE DATABASE

Para incluir la sentencia CREATE DATABASE en el archivo, usa la opción --databases:

mysqldump -u root -p --databases tienda_mysql > tienda_mysql_backup.sql

El archivo resultante comienza con:

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `tienda_mysql`;
USE `tienda_mysql`;

La diferencia es sutil pero importante. Con --databases, la restauración es completamente autónoma: crea la base de datos si no existe y luego restaura su contenido.

Backup de producción completo

Para un respaldo de producción que incluya todos los objetos de la base de datos, combina las opciones esenciales:

mysqldump \
    --single-transaction \
    --routines \
    --triggers \
    --events \
    --databases tienda_mysql \
    -u root -p > /backups/tienda_mysql_$(date +%Y%m%d).sql

La opción --single-transaction garantiza que el backup sea consistente para tablas InnoDB sin bloquear las escrituras. --routines incluye procedimientos almacenados y funciones. --triggers incluye los triggers asociados a las tablas. --events incluye los eventos del scheduler.

Backup solo de la estructura

Si necesitas únicamente el esquema de la base de datos sin los datos, la opción --no-data genera solo las sentencias DDL:

mysqldump --no-data -u root -p tienda_mysql > tienda_mysql_esquema.sql

Esto es útil en varios escenarios. Si quieres mantener el esquema en un sistema de control de versiones como Git, si necesitas replicar la estructura en un servidor de desarrollo, o si quieres documentar el diseño actual de la base de datos.

El archivo resultante contiene todas las sentencias CREATE TABLE con sus columnas, tipos de datos, índices, foreign keys, y opciones de motor:

CREATE TABLE `productos` (
  `id` int NOT NULL AUTO_INCREMENT,
  `nombre` varchar(200) NOT NULL,
  `precio` decimal(10,2) NOT NULL,
  `stock` int DEFAULT '0',
  `categoria_id` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_categoria` (`categoria_id`),
  CONSTRAINT `fk_prod_cat` FOREIGN KEY (`categoria_id`)
    REFERENCES `categorias` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Backup solo de los datos

Lo opuesto al caso anterior: exportar solo los datos sin la estructura de las tablas:

mysqldump --no-create-info -u root -p tienda_mysql > tienda_mysql_datos.sql

Este tipo de backup es útil cuando ya tienes la estructura creada en el destino y solo necesitas cargar o actualizar los datos.

Backup con compresión

Los archivos SQL sin comprimir pueden ser muy grandes. La compresión reduce drásticamente el tamaño:

# Comprimir directamente con gzip
mysqldump --single-transaction --routines --triggers \
    -u root -p tienda_mysql | gzip > /backups/tienda_mysql_$(date +%Y%m%d).sql.gz

Un backup de una base de datos de 5 GB puede reducirse a unos 500 MB con gzip. Para bases de datos más grandes, zstd ofrece mejor compresión con mayor velocidad:

mysqldump --single-transaction --routines --triggers \
    -u root -p tienda_mysql | zstd > /backups/tienda_mysql_$(date +%Y%m%d).sql.zst

Incluir procedimientos almacenados

Si tu base de datos utiliza procedimientos almacenados, funciones o eventos, es crucial incluirlos en el backup. Puedes verificar qué objetos tiene tu base de datos antes de respaldar:

-- Ver procedimientos y funciones
SELECT routine_type, routine_name
FROM information_schema.routines
WHERE routine_schema = 'tienda_mysql';
routine_typeroutine_name
PROCEDUREcalcular_total_pedido
PROCEDUREprocesar_devolucion
FUNCTIONcalcular_descuento
-- Ver eventos programados
SELECT event_name, status
FROM information_schema.events
WHERE event_schema = 'tienda_mysql';
event_namestatus
limpiar_sesiones_expiradasENABLED
generar_reporte_diarioENABLED

Con --routines y --events, todos estos objetos se incluyen en el backup.

Programar backups con cron

La automatización es esencial para que los backups se realicen de forma consistente:

# Editar el crontab
crontab -e
 
# Backup diario a las 2 AM
0 2 * * * mysqldump --single-transaction --routines --triggers --events --defaults-file=/home/admin/.my.cnf tienda_mysql | gzip > /backups/tienda_mysql_$(date +\%Y\%m\%d).sql.gz 2>> /var/log/backup-mysql.log

El archivo .my.cnf almacena las credenciales de forma segura:

# /home/admin/.my.cnf
[mysqldump]
user=backup_user
password=contraseña_segura
# Proteger el archivo de credenciales
chmod 600 /home/admin/.my.cnf

Rotación de backups

Sin una política de rotación, los backups acumulados llenarán el disco. Un script simple puede mantener solo los backups de los últimos N días:

#!/bin/bash
# /scripts/backup-mysql.sh
 
BACKUP_DIR="/backups/mysql"
DIAS_RETENCION=7
FECHA=$(date +%Y%m%d_%H%M%S)
 
# Crear backup
mysqldump --single-transaction --routines --triggers --events \
    --defaults-file=/home/admin/.my.cnf \
    tienda_mysql | gzip > "${BACKUP_DIR}/tienda_mysql_${FECHA}.sql.gz"
 
# Verificar que se creó correctamente
if [ $? -eq 0 ]; then
    echo "[$(date)] Backup completado: tienda_mysql_${FECHA}.sql.gz"
 
    # Eliminar backups antiguos
    find ${BACKUP_DIR} -name "tienda_mysql_*.sql.gz" -mtime +${DIAS_RETENCION} -delete
    echo "[$(date)] Backups con más de ${DIAS_RETENCION} días eliminados"
else
    echo "[$(date)] ERROR: El backup falló" >&2
fi

Verificación del backup

Un backup sin verificar puede fallar cuando más lo necesitas. Después de crear el respaldo, comprueba que es válido:

# Verificar que el archivo comprimido no está corrupto
gzip -t /backups/tienda_mysql_20260214.sql.gz && echo "Archivo válido"
 
# Verificar que contiene sentencias SQL válidas
zcat /backups/tienda_mysql_20260214.sql.gz | tail -5

Las últimas líneas de un backup de mysqldump válido deben verse así:

-- Dump completed on 2026-02-14 02:00:15

Si ves esta línea final, el backup se completó correctamente sin interrupciones.

Restaurar el backup

Para restaurar el backup en el mismo servidor o en otro:

# Si el backup incluye CREATE DATABASE (--databases)
mysql -u root -p < tienda_mysql_backup.sql
 
# Si no incluye CREATE DATABASE
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS tienda_mysql"
mysql -u root -p tienda_mysql < tienda_mysql_backup.sql
 
# Restaurar desde archivo comprimido
zcat /backups/tienda_mysql_20260214.sql.gz | mysql -u root -p tienda_mysql

El backup de una base de datos individual es la operación de respaldo más frecuente en MySQL. Con las opciones correctas y una automatización adecuada, tendrás la tranquilidad de poder recuperar tus datos ante cualquier incidente. En el siguiente artículo veremos cómo respaldar todas las bases de datos de un servidor.

Escrito por Eduardo Lázaro