Percona XtraBackup: Backups en Caliente para MySQL
Percona XtraBackup es la herramienta de backup más utilizada para MySQL y Percona Server que permite realizar backups completos e incrementales sin interrumpir las operaciones de escritura en la base de datos. A diferencia de mysqldump que bloquea las tablas, XtraBackup trabaja a nivel de ficheros InnoDB copiando los datos mientras el servidor sigue funcionando, lo que lo hace indispensable en entornos de producción donde cada segundo de inactividad cuenta.
Requisitos Previos
- MySQL 8.0+ o Percona Server 8.0+
- XtraBackup 8.0+ (debe coincidir con la versión mayor de MySQL)
- Suficiente espacio en disco (al menos igual que el tamaño del datadir de MySQL)
- El usuario de backup necesita permisos específicos en MySQL
# Verificar la versión de MySQL para instalar la versión correcta de XtraBackup
mysql --version
# Crear el usuario de backup en MySQL con los permisos necesarios
mysql -u root -p << 'EOF'
CREATE USER 'xtrabackup'@'localhost' IDENTIFIED BY 'contraseña-backup-segura';
GRANT BACKUP_ADMIN, PROCESS, RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'xtrabackup'@'localhost';
GRANT SELECT ON performance_schema.log_status TO 'xtrabackup'@'localhost';
GRANT SELECT ON performance_schema.keyring_component_status TO 'xtrabackup'@'localhost';
FLUSH PRIVILEGES;
EOF
Instalación de XtraBackup
# Ubuntu/Debian
wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb
dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb
percona-release enable-only tools
apt update && apt install -y percona-xtrabackup-80
# Para CentOS/Rocky Linux 8+
yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm
percona-release enable-only tools
yum install -y percona-xtrabackup-80
# Instalar herramientas auxiliares necesarias
apt install -y qpress lz4 # Para compresión
# Verificar la instalación
xtrabackup --version
Backups Completos
# Backup completo básico al directorio /backups/mysql/
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup-segura \
--target-dir=/backups/mysql/full-$(date +%Y%m%d_%H%M%S)
# Los archivos de backup son copias de los ficheros InnoDB + binlogs
# ANTES de poder restaurar, hay que preparar el backup (aplicar los redo logs)
# Preparar el backup (aplicar transacciones incompletas)
# Esto se hace en el servidor de destino o en local antes de copiar
xtrabackup \
--prepare \
--target-dir=/backups/mysql/full-20240115_020000
# Verificar el estado del backup
ls -la /backups/mysql/full-20240115_020000/
cat /backups/mysql/full-20240115_020000/xtrabackup_info
# Backup completo con opciones adicionales
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup-segura \
--parallel=4 \ # Usar 4 threads para el backup
--rsync \ # Usar rsync para reducir el tiempo de bloqueo
--no-timestamp \ # No crear subdirectorio con timestamp
--target-dir=/backups/mysql/full
Backups Incrementales
Los backups incrementales solo copian las páginas InnoDB modificadas desde el último backup.
# Paso 1: Backup completo inicial (línea base)
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup \
--target-dir=/backups/mysql/base
# Paso 2: Primer backup incremental (desde la base)
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup \
--target-dir=/backups/mysql/inc-1 \
--incremental-basedir=/backups/mysql/base
# Paso 3: Segundo backup incremental (desde el inc-1)
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup \
--target-dir=/backups/mysql/inc-2 \
--incremental-basedir=/backups/mysql/inc-1
# Para restaurar backups incrementales, hay que preparar en orden:
# 1. Preparar la base sin aplicar los redo logs (para poder agregar los incrementales)
xtrabackup \
--prepare \
--apply-log-only \
--target-dir=/backups/mysql/base
# 2. Aplicar el primer incremental
xtrabackup \
--prepare \
--apply-log-only \
--target-dir=/backups/mysql/base \
--incremental-dir=/backups/mysql/inc-1
# 3. Aplicar el segundo incremental (el último NO usa --apply-log-only)
xtrabackup \
--prepare \
--target-dir=/backups/mysql/base \
--incremental-dir=/backups/mysql/inc-2
# Ahora el directorio /backups/mysql/base está listo para restaurar
Streaming a Servidores Remotos
# Hacer backup directamente a un servidor remoto usando ssh
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup \
--stream=xbstream | \
ssh backup@servidor-remoto "xbstream -x -C /backups/mysql/remote-backup"
# Streaming con compresión para reducir el ancho de banda usado
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup \
--compress \
--compress-threads=4 \
--stream=xbstream | \
ssh backup@servidor-remoto "xbstream -x -C /backups/mysql/compressed"
# Streaming a S3 usando mbstream y AWS CLI
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup \
--compress \
--stream=xbstream | \
aws s3 cp - s3://mi-bucket-backups/mysql/backup-$(date +%Y%m%d).xbstream
# Streaming con netcat para transferencias en red local (más rápido que SSH)
# En el servidor destino (primero):
nc -l -p 9999 | xbstream -x -C /backups/mysql/netcat-backup
# En el servidor origen:
xtrabackup \
--backup \
--stream=xbstream | \
nc servidor-destino 9999
Backups Comprimidos y Cifrados
# Backup comprimido con qpress (incluido con XtraBackup)
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup \
--compress \
--compress-threads=4 \
--target-dir=/backups/mysql/compressed-backup
# Descomprimir antes de preparar la restauración
xtrabackup \
--decompress \
--parallel=4 \
--target-dir=/backups/mysql/compressed-backup
# Backup cifrado (usar clave de 24 bytes en base64)
openssl rand -base64 24 > /etc/mysql/backup.key
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup \
--encrypt=AES256 \
--encrypt-key-file=/etc/mysql/backup.key \
--target-dir=/backups/mysql/encrypted-backup
# Descifrar el backup para restaurarlo
xtrabackup \
--decrypt=AES256 \
--encrypt-key-file=/etc/mysql/backup.key \
--target-dir=/backups/mysql/encrypted-backup
# Backup comprimido Y cifrado
xtrabackup \
--backup \
--user=xtrabackup \
--password=contraseña-backup \
--compress \
--compress-threads=4 \
--encrypt=AES256 \
--encrypt-key-file=/etc/mysql/backup.key \
--parallel=4 \
--target-dir=/backups/mysql/backup-$(date +%Y%m%d)
Restauración y Point-in-Time Recovery
# Restauración completa (sustituir el datadir de MySQL)
# Paso 1: Preparar el backup
xtrabackup \
--prepare \
--target-dir=/backups/mysql/full-20240115
# Paso 2: Detener MySQL
systemctl stop mysql
# Paso 3: Mover el datadir actual a un directorio de seguridad
mv /var/lib/mysql /var/lib/mysql.bak
# Paso 4: Crear el directorio nuevo del datadir
mkdir -p /var/lib/mysql
# Paso 5: Copiar los archivos del backup al datadir
xtrabackup \
--copy-back \
--target-dir=/backups/mysql/full-20240115
# O usar rsync para copiar más rápido
rsync -avP /backups/mysql/full-20240115/ /var/lib/mysql/
# Paso 6: Ajustar los permisos
chown -R mysql:mysql /var/lib/mysql
# Paso 7: Iniciar MySQL
systemctl start mysql
# Point-in-Time Recovery: restaurar hasta un momento específico
# XtraBackup guarda el archivo de binlog en la carpeta del backup
cat /backups/mysql/full-20240115/xtrabackup_binlog_info
# Aplicar los binlogs desde el punto del backup hasta el momento deseado
mysqlbinlog \
--start-position=<posicion-del-backup> \
--stop-datetime="2024-01-15 14:30:00" \
/var/log/mysql/mysql-bin.000123 | \
mysql -u root -p
Automatización con Scripts
# Script de backup automatizado con rotación
cat > /usr/local/bin/mysql-backup.sh << 'SCRIPT'
#!/bin/bash
# Script de backup automático de MySQL con XtraBackup
set -euo pipefail
# Configuración
BACKUP_BASE="/backups/mysql"
MYSQL_USER="xtrabackup"
MYSQL_PASS="contraseña-backup-segura"
RETENTION_DAYS=7
LOG_FILE="/var/log/mysql-backup.log"
S3_BUCKET="s3://mi-bucket-backups/mysql"
# Función de logging
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Crear directorio de backup con timestamp
BACKUP_DIR="${BACKUP_BASE}/full-$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
log "Iniciando backup completo en $BACKUP_DIR"
# Realizar el backup
if xtrabackup \
--backup \
--user="$MYSQL_USER" \
--password="$MYSQL_PASS" \
--parallel=4 \
--compress \
--compress-threads=4 \
--target-dir="$BACKUP_DIR" \
2>>"$LOG_FILE"; then
log "Backup completado exitosamente"
else
log "ERROR: El backup falló"
exit 1
fi
# Subir a S3 (opcional)
if command -v aws &> /dev/null; then
log "Subiendo backup a S3..."
aws s3 sync "$BACKUP_DIR" "${S3_BUCKET}/$(basename "$BACKUP_DIR")/" \
--storage-class STANDARD_IA
log "Backup subido a S3"
fi
# Eliminar backups más antiguos que RETENTION_DAYS
log "Limpiando backups con más de $RETENTION_DAYS días..."
find "$BACKUP_BASE" -maxdepth 1 -type d -name "full-*" \
-mtime "+$RETENTION_DAYS" \
-exec rm -rf {} \;
log "Backup finalizado. Espacio disponible: $(df -h "$BACKUP_BASE" | awk 'NR==2{print $4}')"
SCRIPT
chmod +x /usr/local/bin/mysql-backup.sh
# Programar el backup diario con cron (2:00 AM cada día)
echo "0 2 * * * root /usr/local/bin/mysql-backup.sh" > /etc/cron.d/mysql-backup
Solución de Problemas
Error: Cannot connect to the database server:
# Verificar que el usuario tiene los permisos correctos
mysql -u root -p -e "SHOW GRANTS FOR 'xtrabackup'@'localhost';"
# Verificar que MySQL está corriendo
systemctl status mysql
# Intentar conectarse manualmente
mysql -u xtrabackup -p -e "SELECT 1;"
Error: The transaction log size is changed:
# Esto ocurre cuando innodb_log_file_size cambia entre versiones
# Durante el --prepare, especificar el tamaño correcto:
xtrabackup \
--prepare \
--use-memory=2G \
--target-dir=/backups/mysql/backup
El backup es muy lento:
# Aumentar el número de threads paralelos
xtrabackup \
--backup \
--parallel=8 \
--compress-threads=4 \
--user=xtrabackup \
--password=contraseña \
--target-dir=/backups/
# Verificar si InnoDB tiene mucho redo log pendiente
mysql -u root -p -e "SHOW ENGINE INNODB STATUS\G" | grep -A5 "LOG"
Conclusión
Percona XtraBackup es la herramienta estándar para backups de MySQL en producción precisamente porque elimina el requisito de bloquear las tablas durante el proceso. Sus capacidades de backup incremental, streaming y cifrado lo hacen adecuado para cualquier estrategia de backup empresarial: desde un servidor único hasta entornos de replicación complejos donde el tiempo de inactividad es inaceptable. Combinado con una rotación automática y verificación regular de restauraciones, XtraBackup proporciona una estrategia de backup robusta y confiable.


