MySQL Todo Dia: backup incremental diário com mysqlpump e S3
Script pronto para rodar backup full semanal e incrementais diários de MySQL 8 usando mysqlpump, binlogs e storage S3-compatível.

Introdução
Não rodar backup todo dia é corda no pescoço. Em ambiente MySQL 8 você não precisa esperar janela de manutenção infinita: dá para combinar mysqlpump, binlogs e um storage S3-compatível para ter backups incrementais comprimidos e versionados. Claro que existe o xtrabackup, mas, hoje vamos abordar algo 100% nativo, simples, fácil, barato e bonitinho.
Pré-requisitos
MySQL 8.0 com GTID e binlogs habilitados.
Bucket em storage compatível com S3 (MinIO, Wasabi, AWS S3).
Ferramentas instaladas:
mysqlpump,awscliou equivalente.
Backup full semanal
Rode um full toda semana para resetar a cadeia incremental:
#!/bin/bash
set -euo pipefail
DATE=$(date +%Y%m%d-%H%M)
FULL=/backups/mysql/full-$DATE.sql.gz
mysqlpump --exclude-databases=sys,performance_schema --users --events --routines --single-transaction | gzip > "${FULL}"
aws s3 cp "${FULL}" s3://mysql-backups/full/
Incremental diário com binlogs
Use mysqlbinlog para extrair apenas o delta desde o último corte:
#!/bin/bash
set -euo pipefail
LAST_FILE=$(aws s3 ls s3://mysql-backups/incremental/ | tail -n1 | awk '{print $4}')
START_POS=${LAST_FILE##*-}
START_FILE=${LAST_FILE%%-*}
DATE=$(date +%Y%m%d-%H%M)
INC=/backups/mysql/inc-$DATE
mysqlbinlog --raw --read-from-remote-server --host=127.0.0.1 --user=backup --password=... --start-position=${START_POS} --start-datetime="$(date '+%F %T' -d '-1 day')" --stop-never ${START_FILE} > "${INC}.bin"
gzip "${INC}.bin"
aws s3 cp "${INC}.bin.gz" s3://mysql-backups/incremental/
Automação com cron e retenção
Agende o incremental (domingo a sábado) e o full (domingo) no cron:
0 2 * * 0 /usr/local/bin/mysql-full-backup.sh
0 2 * * 1-6 /usr/local/bin/mysql-inc-backup.sh
Configure políticas de lifecycle no bucket para manter 30 dias de incrementais e 12 semanas de full.
Restore rápido
Baixe o último full e os incrementais posteriores.
Restaure o full:
gunzip -c full.sql.gz | mysql.Aplique os binlogs em ordem:
for f in inc-*.bin.gz; do gunzip -c $f | mysqlbinlog - | mysql; done.
Fechamento
Não tem glamour: backup só é bom quando restaura. Combinando mysqlpump, binlogs e S3 você ganha RPO diário sem derrubar aplicação. Ajuste o ciclo conforme o volume e teste o restore todo mês.