DBA Junior Ciberecus MX
Temas · Capítulo 3 · PF-016

Tema 16: Respaldos con mysqldump y pg_dump — la red de seguridad del DBA

#PF-016 | XP: 280 | Insignia: Guardiana del Backup | Tier: Senior | Tiempo: 4 h

Visión mexica — calpixqui resguardando tributos en el calmécac

Objetivo

Al terminar este tema vas a poder ejecutar respaldos lógicos consistentes en MySQL y PostgreSQL, automatizarlos con cron/Task Scheduler, verificar que el respaldo es restaurable, y diseñar una política de retención 3-2-1. También vas a entender por qué un respaldo que nunca se ha restaurado no es un respaldo, es una hipótesis.

Mapa del tema

    La regla 3-2-1 y por qué "tengo un dump" no basta `mysqldump` para MySQL: opciones clave, transacciones, bloqueos `pg_dump` para PostgreSQL: formatos plain, custom y directory Automatización con cron (Linux) y Task Scheduler (Windows) Cifrado del archivo de respaldo y verificación con SHA-256 LAB: cron diario + verificación semanal + alerta por correo

Visión mexica — Por Citlalli

En el altépetl mexica existían tres copias del tributo mayor: una en el calmécac (archivo del templo), otra en el tecpan (palacio del tlatoani) y una tercera que viajaba con el calpixqui cuando partía a las provincias conquistadas. Si una se quemaba, las otras dos permitían reconstruir el registro. Esa es exactamente la regla 3-2-1: tres copias, en dos medios diferentes, con una fuera del sitio.

Cuando un DBA me dice "sí, tengo respaldos" pero nunca los ha restaurado en un entorno de prueba, le respondo lo mismo que le diría a un calpixqui que nunca abrió los tributos guardados: no sabes si están bien hasta que los abres. En este tema aprenderás a hacer dumps verificables, no dumps decorativos.

Regla de oro mexica: el respaldo que no se prueba es fe, no ingeniería.

Bloque 1 — La regla 3-2-1 y por qué "tengo un dump" no basta

El error más caro de un DBA junior es confundir tener un archivo de respaldo con tener un sistema de recuperación. Hay tres problemas clásicos:

    El respaldo existe pero está corrupto (disco dañado, escritura incompleta, encoding roto). El respaldo existe pero nunca se ha restaurado, así que no sabes si la versión es consistente o si le faltan transacciones. El respaldo existe pero está en el mismo disco que la base de datos — un fallo de hardware se lleva todo.
La regla 3-2-1 (propuesta originalmente por Peter Krogh y adoptada por US-CERT, NIST y el CIS) dice:

  • 3 copias de los datos (la original + al menos 2 respaldos).
  • 2 medios diferentes (disco local + cinta, disco + nube, etc.).
  • 1 copia fuera del sitio (otra ciudad, otro proveedor cloud, otra bóveda física).
En la práctica para un DBA junior esto se traduce a:

  • 1 copia viva: la base de datos en producción.
  • 1 respaldo local: disco USB o NAS en la misma oficina.
  • 1 respaldo remoto: S3, Google Cloud Storage, Backblaze B2 o similar.
Y la parte olvidada: una prueba de restauración documentada al menos una vez al mes. Si no puedes restaurar el respaldo de hace 30 días en menos de 30 minutos, no tienes un sistema de recuperación: tienes un archivo grande.


Bloque 2 — `mysqldump` para MySQL: opciones que importan

`mysqldump` produce SQL plano (sentencias `CREATE TABLE` + `INSERT`). Útil para bases pequeñas y medianas (hasta ~50 GB con paciencia). Para bases grandes es mejor `mysqlbackup` (Mysql Enterprise) o `mariabackup` (MariaDB / MySQL 8 con binlogs).

Sintaxis mínima:

mysqldump -u root -p tienda_tlalli > backup_tienda_2026-08-23.sql

Opciones que necesitas dominar:

| Opción | Para qué sirve | Cuándo usarla | |---|---|---| | `--single-transaction` | Genera un dump consistente sin bloquear InnoDB | Siempre en producción con InnoDB | | `--routines` | Incluye procedimientos y funciones almacenadas | Cuando tienes SP/Functions | | `--triggers` | Incluye triggers (sí por defecto, pero documenta) | Siempre | | `--events` | Incluye eventos del event scheduler | Si los usas | | `--add-drop-table` | Agrega DROP TABLE antes de CREATE | Para restauraciones limpias | | `--hex-blob` | Exporta BLOB/TEXT en hex | Para campos binarios con caracteres especiales | | `--default-character-set=utf8mb4` | Fuerza encoding de la salida | Crítico en Windows/XAMPP (latin1 por defecto) | | `--column-statistics=0` | Desactiva estadísticas (compatible con MySQL viejo) | Solo si importas a MySQL 5.x |

Ejemplo para producción (tienda Tlalli, ~50 MB):

mysqldump \
  -u backup_user \
  -p"$(cat ~/.mysql_backup_pwd)" \
  --single-transaction \
  --routines --triggers --events \
  --default-character-set=utf8mb4 \
  --hex-blob \
  tienda_tlalli | gzip > tienda_2026-08-23.sql.gz

Detalle crítico en XAMPP/Windows: el cliente `mysql.exe` y `mysqldump.exe` de XAMPP usan cp1252 por defecto, no UTF-8. Si haces un dump sin `--default-character-set=utf8mb4`, los acentos del nombre "Xochitl Hernández Ruiz" llegan rotos. Siempre agrega la flag.

Para verificar el contenido sin restaurar (revisión rápida):

gunzip -c tienda_2026-08-23.sql.gz | grep -i "INSERT INTO clientes" | head -5

Bloque 3 — `pg_dump` para PostgreSQL: tres formatos para tres casos

PostgreSQL ofrece tres formatos de respaldo con `pg_dump`, cada uno con trade-offs distintos:

Formato `plain` (por defecto)

Genera un archivo `.sql` con `CREATE TABLE` + `COPY ... FROM stdin`.

pg_dump -U postgres -h localhost -d tienda_tlalli -F p -f backup_tienda.sql

  • Pro: legible, editable, se puede inspeccionar con `less`.
  • Contra: muy lento para restaurar tablas grandes (ejecuta un `INSERT` por fila).

Formato `custom` (recomendado)

Archivo binario comprimido, restaurable solo con `pg_restore`.

pg_dump -U postgres -h localhost -d tienda_tlalli -F c -f backup_tienda.dump

  • Pro: comprimido, permite restaurar tablas individuales (`pg_restore --table=clientes`), paralelizable.
  • Contra: no es legible en texto plano.

Formato `directory`

Genera un directorio con un archivo por tabla, paralelizable.

pg_dump -U postgres -h localhost -d tienda_tlalli -F d -j 4 -f backup_dir/

  • Pro: el más rápido para bases grandes (TB), usa múltiples workers.
  • Contra: requiere directorio, no un solo archivo.
Tabla comparativa:

| Caso de uso | Formato | Comando de respaldo | Comando de restauración | |---|---|---|---| | Inspección manual / debug | `plain` | `pg_dump -F p ...` | `psql -f backup.sql` | | Respaldo diario producción | `custom` | `pg_dump -F c ...` | `pg_restore -d tienda backup.dump` | | Respaldo paralelo (TB) | `directory` | `pg_dump -F d -j 8 ...` | `pg_restore -j 8 ...` | | Migración entre versiones | `plain` | `pg_dump -F p ...` | `psql -f backup.sql` |

Para `tienda_tlalli` (110 pedidos, ~5 MB), el formato `custom` es el balance ideal.


Bloque 4 — Automatización: cron en Linux, Task Scheduler en Windows

Un respaldo que depende de que te acuerdes de hacerlo está roto. Hay que automatizarlo.

Linux/macOS con cron

Edita tu crontab:

crontab -e

Agrega:

# Respaldo diario de MySQL a las 2 AM, conservando 7 días
0 2    /opt/backups/scripts/backup_mysql.sh >> /var/log/backup_mysql.log 2>&1

Respaldo diario de PostgreSQL a las 3 AM

0 3
/opt/backups/scripts/backup_postgres.sh >> /var/log/backup_postgres.log 2>&1

El script `/opt/backups/scripts/backup_mysql.sh`:

#!/usr/bin/env bash
set -euo pipefail
FECHA=$(date +%Y-%m-%d_%H%M)
DEST=/opt/backups/mysql
mysqldump -u backup_user -p"${MYSQL_PWD}" \
  --single-transaction --routines --triggers --events \
  --default-character-set=utf8mb4 \
  tienda_tlalli | gzip > "$DEST/tienda_${FECHA}.sql.gz"
sha256sum "$DEST/tienda_${FECHA}.sql.gz" > "$DEST/tienda_${FECHA}.sha256"

Borrar respaldos de más de 7 días

find "$DEST" -name "tienda_.sql.gz" -mtime +7 -delete

Detalle de seguridad: la contraseña va en una variable de entorno (`MYSQL_PWD`) o en un archivo `.my.cnf` con permisos `chmod 600`. Nunca en la línea de comandos visible en `ps`.

Windows con Task Scheduler

PowerShell script `C:\backups\backup_mysql.ps1`:

$fecha = Get-Date -Format "yyyy-MM-dd_HHmm"
$dest = "C:\backups\mysql"
$cn   = "mysql"
& "C:\xampp8\mysql\bin\mysqldump.exe" `
    -u backup_user --default-character-set=utf8mb4 `
    --single-transaction --routines --triggers --events `
    tienda_tlalli | Compress-Archive -DestinationPath "$dest\tienda_$fecha.sql.zip" -Force
Get-FileHash "$dest\tienda_$fecha.sql.zip" -Algorithm SHA256 |
    Export-Csv "$dest\tienda_$fecha.sha256.csv" -NoTypeInformation
Get-ChildItem "$dest\tienda_.sql.zip" |
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } |
    Remove-Item

Programa la tarea con `schtasks /Create /SC DAILY /TN "BackupMySQL" /TR "powershell -File C:\backups\backup_mysql.ps1" /ST 02:00`.


Bloque 5 — Cifrado y verificación con SHA-256

Un respaldo sin cifrado que sale de tu servidor es un regalo para el primero que lo intercepta. Si el archivo contiene datos personales de clientes (nombre, email, teléfono), las implicaciones legales en México con la LFPDPPP son serias.

Opciones para cifrar el archivo:

  • gpg (GnuPG): estándar de oro, gratis, multiplataforma.
gpg --symmetric --cipher-algo AES256 backup_tienda.sql.gz

Te pide passphrase, genera backup_tienda.sql.gz.gpg

  • openssl:
openssl enc -aes-256-cbc -salt -in backup_tienda.sql.gz -out backup.tienda.sql.gz.enc

Y la verificación: el SHA-256 del archivo original debe coincidir con el SHA-256 después de la restauración. Si no coinciden, el archivo está corrupto. En el script ya se genera con `sha256sum`. Para verificar después de restaurar:

# Restaurar en directorio temporal
zcat backup_tienda.sql.gz | mysql -u root -p test_restore
mysqldump -u root -p --single-transaction test_restore | sha256sum

Compara con el hash guardado

Si los hashes no coinciden: el respaldo está corrupto. Investiga disco, memoria, canal de transferencia.


AI Mission

Pídele a tu IA copiloto (Claude, ChatGPT, Gemini) que audite tu política de respaldos. Pega este prompt y adapta la respuesta:

Actúa como un DBA senior revisando la política de respaldos de un junior.
Aquí está mi contexto:
  • Bases: tienda_tlalli en MySQL 8 (5 MB, InnoDB) y la misma en PostgreSQL 16
  • Frecuencia actual de respaldos: manual, cuando me acuerdo
  • Almacenamiento: solo en la misma laptop
  • Restauración probada por última vez: nunca
Dame:
    Los 5 huecos más críticos de mi política. Un script de bash para Linux que haga respaldo diario automatizado
con verificación SHA-256 y rotación de 7 días.
    Una checklist mensual de 4 pasos para probar la restauración.
Compara la respuesta con lo que aprendiste en este tema. Si la IA recomienda algo contradictorio (por ejemplo, "no necesitas SHA-256, MySQL ya lo valida"), decide con criterio propio: MySQL no verifica la integridad del archivo de respaldo al restaurarlo, solo la sintaxis SQL.


Errores típicos

    Dump sin `--single-transaction` en InnoDB de producción → puede bloquear toda la base durante minutos. Olvidar `--default-character-set=utf8mb4` en XAMPP/Windows → acentos rotos al restaurar en otro equipo. Confundir `mysqldump` con respaldo físico → `mysqldump` es lógico, no copia los binlogs. Para PITR necesitas binlogs. No probar la restauración → tener 200 GB de dumps y descubrir que están corruptos el día del incidente. Permisos del usuario de respaldo → usar `root` para respaldar es un riesgo de seguridad; crea un usuario con `SELECT, LOCK TABLES, RELOAD, SHOW VIEW, EVENT, TRIGGER` solamente. Almacenar el dump en el mismo disco → un fallo de disco se lleva producción y respaldo.

LAB práctico — Política de respaldo 3-2-1 automatizada

Objetivo: dejar tienda_tlalli con respaldo diario automatizado, cifrado, con verificación SHA-256 y una copia fuera del sitio.

Requisitos: MySQL 8 y/o PostgreSQL 16 funcionando con la BD `tienda_tlalli`, ~30 MB libres en disco.

Paso 1 — Crear el usuario de respaldo

MySQL:

CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'ClaveSegura_2026!';
GRANT SELECT, LOCK TABLES, RELOAD, SHOW VIEW, EVENT, TRIGGER ON tienda_tlalli. TO 'backup_user'@'localhost';
FLUSH PRIVILEGES;

PostgreSQL:

CREATE ROLE backup_user WITH LOGIN PASSWORD 'ClaveSegura_2026!';
GRANT CONNECT ON DATABASE tienda_tlalli TO backup_user;
GRANT USAGE ON SCHEMA public TO backup_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO backup_user;

Paso 2 — Script de respaldo Linux (adapta a Windows si aplica)

Guarda como `/opt/backups/backup_tienda.sh`:

#!/usr/bin/env bash
set -euo pipefail
FECHA=$(date +%Y-%m-%d_%H%M)
DEST=/opt/backups/tienda_tlalli
mkdir -p "$DEST"

1. Dump MySQL

mysqldump -u backup_user -p"${MYSQL_PWD}" \ --single-transaction --routines --triggers --events \ --default-character-set=utf8mb4 \ tienda_tlalli | gzip > "$DEST/mysql_${FECHA}.sql.gz"

2. Dump PostgreSQL (formato custom)

pg_dump -U backup_user -h localhost -F c \ -f "$DEST/pg_${FECHA}.dump" tienda_tlalli

3. Hash SHA-256

sha256sum "$DEST/mysql_${FECHA}.sql.gz" "$DEST/pg_${FECHA}.dump" > "$DEST/${FECHA}.sha256"

4. Cifrar con GPG (passphrase en variable de entorno)

echo "${BACKUP_GPG_PWD}" | gpg --batch --yes --passphrase-fd 0 \ --symmetric --cipher-algo AES256 \ "$DEST/mysql_${FECHA}.sql.gz" echo "${BACKUP_GPG_PWD}" | gpg --batch --yes --passphrase-fd 0 \ --symmetric --cipher-algo AES256 \ "$DEST/pg_${FECHA}.dump"

5. Copiar a S3 (fuera del sitio)

aws s3 cp "$DEST/mysql_${FECHA}.sql.gz.gpg" s3://ciberecus-backups/tienda/ 2>/dev/null || true aws s3 cp "$DEST/pg_${FECHA}.dump.gpg" s3://ciberecus-backups/tienda/ 2>/dev/null || true

6. Rotación 7 días

find "$DEST" -name "
.gz" -mtime +7 -delete find "$DEST" -name ".dump" -mtime +7 -delete find "$DEST" -name ".gpg" -mtime +7 -delete

echo "[OK] Respaldo ${FECHA} completado."

Paso 3 — Probar la restauración

Restaurar en una base temporal:

# MySQL: crear BD de prueba, restaurar, contar filas
mysql -u root -p -e "CREATE DATABASE test_restore;"
gunzip -c /opt/backups/tienda_tlalli/mysql_2026-08-23_0200.sql.gz |
  mysql -u root -p test_restore
mysql -u root -p -e "SELECT COUNT() FROM test_restore.pedidos;"

Esperado: 110

PostgreSQL: crear BD, restaurar, contar filas

createdb -U postgres test_restore_pg pg_restore -U postgres -d test_restore_pg /opt/backups/tienda_tlalli/pg_2026-08-23_0200.dump psql -U postgres -d test_restore_pg -c "SELECT COUNT(
) FROM pedidos;"

Esperado: 110

Paso 4 — Verificar SHA-256

cd /opt/backups/tienda_tlalli
sha256sum -c 2026-08-23_0200.sha256

Debe decir: OK

Si dice `FAILED`, el archivo está corrupto. Investiga antes del próximo ciclo.

Paso 5 — Automatizar con cron

chmod +x /opt/backups/backup_tienda.sh
crontab -e

Agregar:

0 2 * /opt/backups/backup_tienda.sh >> /var/log/backup_tienda.log 2>&1

Entregables del LAB

  • [ ] Script `backup_tienda.sh` ejecutándose sin errores.
  • [ ] Archivos `.gz` y `.dump` generándose diariamente.
  • [ ] Hash SHA-256 verificado en al menos 3 ciclos.
  • [ ] Restauración probada en `test_restore` con conteo de filas correcto.
  • [ ] Al menos una copia en S3 u otro servicio fuera del sitio.

Quest

Preguntas de opción múltiple (10)

1. ¿Cuál es la diferencia principal entre `mysqldump` y un respaldo físico de InnoDB?

A. `mysqldump` es más rápido en bases grandes. B. `mysqldump` produce SQL lógico, no copia los archivos de datos crudos. C. El respaldo físico solo funciona con MyISAM. D. No hay diferencia, son sinónimos.

2. ¿Por qué es importante usar `--single-transaction` en `mysqldump` con InnoDB?

A. Hace que el dump sea más pequeño. B. Genera un dump consistente sin bloquear lecturas ni escrituras prolongadas. C. Activa el modo de cifrado de la base. D. Reduce el uso de CPU a la mitad.

3. ¿Qué formato de `pg_dump` es mejor para restaurar tablas individuales?

A. `plain` B. `custom` C. `directory` D. `tar`

4. La regla 3-2-1 significa:

A. Tres respaldos, dos discos, una contraseña. B. Tres copias, dos medios, una fuera del sitio. C. Tres servidores, dos versiones, una licencia. D. Tres bases, dos motores, una aplicación.

5. ¿Qué opción de `mysqldump` es crítica en XAMPP/Windows para evitar acentos rotos?

A. `--no-data` B. `--default-character-set=utf8mb4` C. `--compress` D. `--skip-lock-tables`

6. ¿Por qué es importante generar y verificar el SHA-256 del respaldo?

A. Para acelerar la restauración. B. Para detectar corrupción o modificación del archivo. C. Para comprimir mejor el archivo. D. Para permitir la restauración remota.

7. ¿Qué usuario es el más seguro para correr respaldos automáticos en MySQL?

A. `root` B. Un usuario dedicado con permisos mínimos: `SELECT, LOCK TABLES, RELOAD`. C. El usuario de la aplicación. D. `admin`.

8. ¿Cuál es la frecuencia mínima recomendada para probar restauraciones?

A. Cada vez que se hace un respaldo. B. Una vez al mes. C. Una vez al año. D. Solo cuando hay un incidente.

9. En PostgreSQL, ¿qué formato de `pg_dump` es el más rápido para bases de terabytes?

A. `plain` B. `custom` C. `directory` con `-j N` workers. D. `tar`.

10. ¿Qué herramienta se usa típicamente para cifrar respaldos con AES-256 desde la línea de comandos?

A. `tar` B. `gpg` o `openssl`. C. `zip` con contraseña. D. `rsync`.

Preguntas abiertas (3)

A. Explica con tus palabras por qué un respaldo que nunca se ha probado no puede considerarse un respaldo válido. Da un ejemplo real (puede ser hipotético) de cuándo un DBA descubriría esto de la peor manera.

B. Compara los formatos `plain`, `custom` y `directory` de `pg_dump`. Para una base de datos de una tienda en línea de 500 GB con 200 tablas, ¿cuál elegirías y por qué? Considera tiempo de respaldo, tiempo de restauración y capacidad de restaurar tablas individuales.

C. Diseña una política de retención para tienda_tlalli (5 MB hoy, proyección 2 GB en 2 años) que cumpla 3-2-1. Especifica: dónde vive cada copia, cuánto tiempo se conserva, quién tiene acceso, y cómo se prueba la restauración.


Respuestas modelo

1. B — `mysqldump` produce SQL lógico (sentencias CREATE + INSERT), no copia los archivos `.ibd` ni los binlogs. El respaldo físico (con `mysqlbackup`, `mariabackup` o `xtrabackup`) clona el directorio de datos y es mucho más rápido para bases grandes. La A es falsa: el respaldo físico es más rápido en bases grandes. La C es falsa: existen para InnoDB. La D es falsa: son diferentes en propósito y rendimiento.

2. B — `--single-transaction` usa una transacción consistente (REPEATABLE READ) que evita bloqueos prolongados. Para InnoDB es la forma estándar de respaldar en producción sin downtime. La A es irrelevante al tamaño. La C es falsa: no cifra. La D es falsa: no reduce CPU.

3. B — El formato `custom` (binario comprimido) permite restaurar tablas individuales con `pg_restore --table=clientes`. El `plain` ejecuta todo en bloque. El `directory` permite extraer archivos específicos pero es más complejo. La D (`tar`) no es un formato de `pg_dump`.

4. B — 3 copias, 2 medios, 1 fuera del sitio. Es la definición adoptada por NIST y CIS. La A es una invención. La C y D son distractores sin relación con respaldos.

5. B — En Windows/XAMPP, el cliente `mysql.exe` y `mysqldump.exe` usan cp1252 por defecto. Sin `--default-character-set=utf8mb4`, los acentos (Xochitl, Ramírez) se pierden. La A es para no incluir datos, no para encoding. La C es para transmisión. La D cambia el comportamiento de bloqueos.

6. B — SHA-256 detecta si el archivo fue modificado, truncado o corrompido en tránsito o en disco. Es un checksum criptográfico que no se puede falsear sin que se note. La A no es su propósito. La C no comprime. La D no es función de hashing.

7. B — Principio de menor privilegio. El usuario de respaldo solo necesita `SELECT` (para leer datos), `LOCK TABLES` (para consistencia en MyISAM, opcional en InnoDB), `RELOAD` (para `FLUSH TABLES`), `SHOW VIEW`, `EVENT`, `TRIGGER`. `root` tiene más permisos de los necesarios y compromete toda la base si se filtra. La C es un riesgo similar.

8. B — Mensual. Cada respaldo es teórico hasta que se restaura. Una vez al mes es el balance entre costo operacional y detección temprana de problemas. La A es operacionalmente inviable. La C es riesgosa: un año de respaldos sin probar es un año de fe ciega. La D es tarde: ya hubo un incidente.

9. C — El formato `directory` con `-j N` workers paraleliza el respaldo y la restauración. Para 500 GB, la diferencia entre `plain` y `directory` con 8 workers puede ser de horas a minutos. La A es la más lenta. La B no paraleliza. La D no existe en `pg_dump`.

10. B — `gpg --symmetric` y `openssl enc -aes-256-cbc` son las dos herramientas estándar de cifrado desde línea de comandos. `tar` no cifra por defecto. `zip` con contraseña usa ZipCrypto (débil). `rsync` sincroniza, no cifra.


Tras las huellas — Por Citlalli

Cuando los españoles quemaron los archivos del calmécac en 1521, los frailes encontraron en los codex sobrevivientes los tributos de los últimos 50 años. Los mexicas no perdieron toda su historia porque tuvieron tres copias en lugares diferentes, incluido un archivo de tributos que se enviaba a otra provincia anualmente.

En tu trabajo de DBA vas a experimentar el equivalente moderno: un disco duro que falla, un servidor secuestrado por ransomware, una consulta que borra la tabla equivocada. En cada uno de esos momentos vas a agradecer haber automatizado los respaldos, haberlos probado y haber guardado una copia fuera del sitio.

Pregunta para el cuaderno: ¿qué pasa hoy mismo si se cae tu disco duro? ¿Cuánto tardarías en restaurar tienda_tlalli? ¿Tienes un respaldo probado de los últimos 7 días? Si la respuesta es "no sé" o "nunca lo he probado", este tema es tu día de comienzo.

Cierre del cuaderno

Líneas para tu cuaderno físico (escribe a mano, no en pantalla):

    Diferencia entre respaldo lógico (mysqldump, pg_dump) y respaldo físico (xtrabackup, mariabackup, snap de FS). Cuándo usar formato `plain`, `custom` o `directory` de `pg_dump`. Por qué la regla 3-2-1 no es opcional en producción. Comando exacto que usaría para restaurar tienda_tlalli en una base `test_restore`. ¿Cuándo fue la última vez que restauré un respaldo de verdad?