Workstation Logo
Produtos
Labs de IAAgentes OpenAIAgentes ClaudeGrok BotWorkstation CRM (WSL CRM)MarketingTodos os Produtos
Soluções IA
Estações de Trabalho IAAI SME PackagesIA PrivadaClusters GPUIA EdgeLaboratório IA EmpresarialIA por Indústria
Serviços
Modernização de plataformaEngenharia digitalFundações de dados e IAOperações autónomasConsultoria de IAAutomação DevOpsCibersegurançaDesenvolvimento de softwareConstrução de agentesConfiguração MLOps
Sobre Nós
ParceirosHistórias de Clientes
Artigos
Documentação
WSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7
Blog
Contacte-nosLogin
Workstation

Estações de trabalho de IA, software multiagente de IA, infraestrutura de GPU e soluções de agentes inteligentes para empresas modernas.

Contacte-nos

Soluções de IA

Estações de Trabalho IAAI SME PackagesIA PrivadaClusters GPUIA EdgeLaboratório IA EmpresarialIA por Indústria

Produtos

Todos os ProdutosWSL CRM e ERPMarketingAgentes OpenAIWSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7

Empresa

Sobre NósPor que WorkstationParceirosHistórias de ClientesPreçosContato

Recursos

ArtigosDocumentaçãoBlogPesquisarMapa do Site
Escritório Reino Unido
77-79 Marlowes, Hemel Hempstead HP1 1LFComo chegar: pegue a saída 20 da M25, Outer LondonN.º da empresa: 11641870Seg - Sex: 9:00 - 18:00 GMT
+44 7515 356 146
Escritório Bélgica
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683Seg - Sex: 9:00 - 18:00 CET
+32 492 45 67 46
Escritório Índia
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI. Todos os direitos reservados.

PrivacidadeCookiesTermos de ServiçoMapa do site

Loading blog...

Home / Blog
DatabaseDevOpsKubernetesBackend

Estratégias de backup de banco de dados de produção que realmente funcionam: MySQL e PostgreSQL

Estratégias comprovadas de backup e recuperação para MySQL e PostgreSQL em produção

Balinder Walia12 de abril de 202633 min read

A perda de dados de produção é o tipo de incidente que encerra carreiras, fecha empresas e chega à primeira página do Hacker News pelos motivos errados. No entanto, a maioria das equipes trata os backups de banco de dados como uma reflexão tardia – um cron job que alguém configurou há dois anos e que ninguém verificou desde então. Este artigo apresenta estratégias de backup testadas em batalha para MySQL e PostgreSQL que foram comprovadas em ambientes de produção que vão desde clusters k3s de nó único até implantações em nuvem multirregionais que processam milhões de transações diariamente.

Cobriremos todo o espectro: métodos de backup lógico e físico, recuperação pontual, agendamento automatizado, alvos de armazenamento em nuvem, criptografia, verificação, abordagens nativas do Kubernetes e o planejamento de recuperação de desastres que une tudo isso. Cada recomendação vem com configuração e código concretos que você pode adaptar ao seu ambiente.

Compreendendo os tipos de backup

Antes de mergulhar em ferramentas específicas, você precisa de um modelo mental claro das quatro estratégias fundamentais de backup e de como elas interagem com os objetivos de recuperação. Cada estratégia faz uma compensação diferente entre velocidade de backup, consumo de armazenamento e tempo de recuperação.

Um backup completo doOcaptura todo o banco de dados em um único momento. É o mais simples de raciocinar e o mais rápido de restaurar, mas também o mais caro em termos de armazenamento e o mais lento de criar. Um backup incrementalOcaptura apenas os dados que foram alterados desde o último backup de qualquer tipo. É rápido de criar e compactar no armazenamento, mas a restauração requer a repetição de toda a cadeia: o último backup completo mais todos os incrementais subsequentes. Um backup diferencialOcaptura tudo o que mudou desde o último backup completo. Ele ocupa um meio-termo – maior que um incremental, mas mais simples de restaurar porque você só precisa do último completo mais o último diferencial. Por fim, o arquivamento contínuo(arquivamento WAL no PostgreSQL, streaming de log binário no MySQL) captura cada transação individual conforme ela acontece, permitindo a recuperação pontual a qualquer momento entre os backups.

Visão geral da estratégia de backup: completo vs incremental vs diferencial vs contínuoDia 0Dia 1Dia 2Dia 3Dia 4Dia 5CompletoIncr.Diferença.WAL/BinlogCOMPLETO (100%)COMPLETO (100%)+5%+3%+4%+2%+5%+8%+12%+14%WAL contínuo / fluxo de log binário (cada transação)Alvo de recuperaçãoBackup completoIncrementalDiferencialFluxo WAL/BinlogPonto de recuperação

A estratégia ideal para a maioria dos sistemas de produção é uma combinação: backups completos semanais, incrementais ou diferenciais diários e arquivamento WAL/binlog contínuo. Isso oferece recuperação rápida de backups completos recentes e a capacidade de recuperação a qualquer momento quando necessário.

Métodos de backup

MySQL

MySQL oferece diversas ferramentas de backup, cada uma adequada para diferentes tamanhos de banco de dados e requisitos de recuperação. A escolha certa depende do volume de dados, da janela de backup aceitável e dos objetivos de RTO/RPO.

mysqldump — O Backup Lógico Universal

mysqldumpproduz instruções SQL que recriam o esquema e os dados. Ele funciona em todas as versões e mecanismos de armazenamento do MySQL, tornando-o um substituto universal. No entanto, ele bloqueia tabelas durante o dump (a menos que use--single-transactioncom InnoDB) e a velocidade de restauração diminui significativamente para bancos de dados além de 50–100 GB porque reproduz instruções INSERT individuais.

# Full logical backup with consistent snapshot for InnoDB
mysqldump --single-transaction --routines --triggers --events \
  --set-gtid-purged=ON --all-databases \
  | gzip > /backups/mysql-full-$(date +%Y%m%d-%H%M%S).sql.gz

# Single database backup with compression
mysqldump --single-transaction --routines --triggers \
  --databases production_db \
  | pigz -p4 > /backups/production_db-$(date +%Y%m%d).sql.gz

# Schema-only backup for migration planning
mysqldump --no-data --routines --triggers --events \
  --all-databases > /backups/schema-only-$(date +%Y%m%d).sql

mysqlpump — Backup lógico paralelo

mysqlpumpmelhora omysqldumpcom despejo de tabela paralelo e compactação integrada. Pode reduzir significativamente o tempo de backup para bancos de dados com muitas tabelas independentes.

# Parallel logical backup with 4 threads and zstd compression
mysqlpump --default-parallelism=4 --compress-output=ZSTD \
  --include-databases=production_db,analytics_db \
  --set-gtid-purged=ON \
  > /backups/mysql-pump-$(date +%Y%m%d).sql.zst

Percona XtraBackup — Backups físicos para InnoDB

Para bancos de dados maiores que 50 GB, os backups lógicos tornam-se impraticáveis — tanto a janela de backup quanto o tempo de restauração crescem linearmente com o tamanho dos dados. O Percona XtraBackup faz cópias de nível físico dos arquivos de dados do InnoDB sem bloquear o banco de dados, tornando-o adequado para implantações de vários terabytes.

# Full physical backup with streaming to compressed archive
xtrabackup --backup --target-dir=/backups/full-$(date +%Y%m%d) \
  --user=backup_user --password=secure_pass \
  --parallel=4 --compress --compress-threads=4

# Incremental backup based on last full
xtrabackup --backup --target-dir=/backups/incr-$(date +%Y%m%d) \
  --incremental-basedir=/backups/full-20260412 \
  --user=backup_user --password=secure_pass \
  --parallel=4

# Stream full backup directly to S3 via xbstream
xtrabackup --backup --stream=xbstream --compress \
  --user=backup_user --password=secure_pass | \
  aws s3 cp - s3://db-backups/mysql/full-$(date +%Y%m%d).xbstream

# Prepare for restore (apply redo log)
xtrabackup --prepare --target-dir=/backups/full-20260412

# Prepare incremental on top of full
xtrabackup --prepare --apply-log-only --target-dir=/backups/full-20260412
xtrabackup --prepare --target-dir=/backups/full-20260412 \
  --incremental-dir=/backups/incr-20260412

# Restore
systemctl stop mysqld
xtrabackup --copy-back --target-dir=/backups/full-20260412
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld
Log binário

MySQL — Recuperação pontual

Os logs binários

MySQL registram cada instrução de modificação de dados ou alteração de linha. Quando combinados com um backup completo ou físico, eles permitem a recuperação pontual a qualquer momento após a realização do backup.

# Enable binary logging in my.cnf
[mysqld]
server-id = 1
log-bin = /var/log/mysql/mysql-bin
binlog_format = ROW
binlog_expire_logs_seconds = 604800   # 7 days
sync_binlog = 1
gtid_mode = ON
enforce_gtid_consistency = ON

# Flush and archive binary logs
mysqladmin flush-logs
mysqlbinlog --read-from-remote-server --host=db-primary \
  --raw --stop-never --result-file=/backup/binlogs/ \
  mysql-bin.000042

# Point-in-time recovery: replay binlog up to specific timestamp
mysqlbinlog --stop-datetime="2026-04-12 14:30:00" \
  /backup/binlogs/mysql-bin.000042 \
  /backup/binlogs/mysql-bin.000043 | mysql -u root
Métodos de backup

PostgreSQL

O ecossistema de backup do

PostgreSQL é indiscutivelmente mais rico que o do MySQL, com ferramentas originais e um conjunto maduro de soluções comunitárias desenvolvidas especificamente para ambientes de produção em grande escala.

pg_dump e pg_dumpall — Backups lógicos

Assim como omysqldump, opg_dumpproduz backups lógicos. O formato personalizado (-Fc) é o padrão recomendado porque suporta restauração paralela, restauração seletiva de tabela e compactação integrada.

# Custom format with parallel dump (4 worker jobs)
pg_dump -Fc -j4 -f /backups/production-$(date +%Y%m%d).dump production_db

# Directory format for maximum parallelism on large databases
pg_dump -Fd -j8 -f /backups/production-$(date +%Y%m%d)/ production_db

# All databases including globals (roles, tablespaces)
pg_dumpall > /backups/pg-all-$(date +%Y%m%d).sql

# Parallel restore from custom format
pg_restore -j4 -d production_db_restored /backups/production-20260412.dump

# Selective restore: single table
pg_restore -j4 -d production_db -t orders /backups/production-20260412.dump

pg_basebackup — Fundação de backup físico

pg_basebackupfaz uma cópia física de todo o diretório de dados PostgreSQL. É a base para recuperação autônoma e configuração de replicação de streaming. Combinado com o arquivamento WAL, permite a recuperação pontual.

# Physical backup with WAL files included
pg_basebackup -D /backups/base-$(date +%Y%m%d) \
  -Ft -z -Xs -P -c fast \
  -U replication_user -h db-primary

# Stream backup directly to a tar archive with checksums
pg_basebackup -D - -Ft -Xs -c fast \
  -U replication_user -h db-primary | \
  gzip > /backups/pg-base-$(date +%Y%m%d).tar.gz

pgBackRest — Gerenciamento de backup de nível empresarial

pgBackRest é o padrão ouro para gerenciamento de backup PostgreSQL. Ele oferece suporte a backups completos, incrementais e diferenciais, backup e restauração paralelos, criptografia, destinos de vários repositórios (disco local, S3, GCS, Azure Blob) e arquivamento WAL automatizado — tudo por meio de uma configuração única e coesa.

# /etc/pgbackrest/pgbackrest.conf
[global]
repo1-type=s3
repo1-s3-bucket=pg-backups-production
repo1-s3-endpoint=s3.eu-west-1.amazonaws.com
repo1-s3-region=eu-west-1
repo1-s3-key=AKIAIOSFODNN7EXAMPLE
repo1-s3-key-secret=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
repo1-path=/pgbackrest
repo1-retention-full=4
repo1-retention-diff=14
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=a_very_secure_encryption_passphrase

# Second repository for geographic redundancy
repo2-type=azure
repo2-azure-container=pg-backups-dr
repo2-azure-account=prodbackupstorage
repo2-azure-key=base64encodedkeyhere
repo2-path=/pgbackrest
repo2-retention-full=2

process-max=4
compress-type=zst
compress-level=6
log-level-console=info
log-level-file=detail
start-fast=y

[production]
pg1-path=/var/lib/postgresql/16/main
pg1-port=5432

# PostgreSQL WAL archive configuration (postgresql.conf)
# archive_mode = on
# archive_command = 'pgbackrest --stanza=production archive-push %p'

# Create the stanza
pgbackrest --stanza=production stanza-create

# Verify the stanza configuration
pgbackrest --stanza=production check

# Full backup
pgbackrest --stanza=production --type=full backup

# Differential backup
pgbackrest --stanza=production --type=diff backup

# Incremental backup
pgbackrest --stanza=production --type=incr backup

# List backups
pgbackrest --stanza=production info

WAL-G — Arquivamento WAL leve para armazenamento em nuvem

WAL-G é uma alternativa mais simples ao pgBackRest que se concentra no streaming de segmentos WAL e backups básicos para armazenamento de objetos em nuvem. É popular em ambientes em contêineres onde você deseja um único binário com configuração mínima.

# Environment variables for WAL-G with S3
export WALG_S3_PREFIX=s3://pg-wal-archive/production
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export AWS_REGION=eu-west-1
export WALG_COMPRESSION_METHOD=lz4
export PGHOST=/var/run/postgresql

# Configure WAL archiving in postgresql.conf
# archive_mode = on
# archive_command = 'wal-g wal-push %p'
# restore_command = 'wal-g wal-fetch %f %p'

# Take a base backup
wal-g backup-push /var/lib/postgresql/16/main

# List backups
wal-g backup-list

# Restore from latest backup
wal-g backup-fetch /var/lib/postgresql/16/main LATEST

# Delete old backups (retain last 4)
wal-g delete retain FULL 4 --confirm

Barman — Servidor de backup centralizado

O

Barman (Backup and Recovery Manager) foi projetado para ambientes onde um servidor de backup dedicado gerencia backups para múltiplas instâncias PostgreSQL. Ele suporta protocolos de replicação rsync/SSH e streaming para transporte de backup.

# /etc/barman.d/production.conf
[production]
description = "Production PostgreSQL 16"
ssh_command = ssh postgres@db-primary
conninfo = host=db-primary user=barman dbname=postgres
streaming_conninfo = host=db-primary user=streaming_barman
backup_method = postgres
streaming_archiver = on
slot_name = barman
retention_policy = RECOVERY WINDOW OF 14 DAYS

# Create replication slot and start streaming
barman receive-wal --create-slot production
barman switch-wal --force --archive production

# Take a backup
barman backup production

# List backups
barman list-backup production

# Restore to point in time
barman recover --target-time "2026-04-12 14:30:00" \
  production 20260412T120000 /var/lib/postgresql/16/main

Recuperação pontual (PITR)

A recuperação pontual do

é o recurso mais importante em seu kit de ferramentas de backup. Ele permite restaurar um banco de dados para o estado exato em que se encontrava em qualquer momento específico — não apenas quando os backups foram feitos, mas a qualquer segundo entre os backups. Isso é fundamental para a recuperação de exclusão acidental de dados, bugs de aplicativos que corrompem dados e incidentes de segurança em que você precisa identificar o momento exato do comprometimento.

Linha do tempo de recuperação pontual (PITR)00:00Sol06:0012:0018:0000:00SegBackup completopg_basebackup@ 00:00WAL / Segmentos de log binário (contínuo)✖TABELA DE QUEDAàs 16:42:31Alvo de recuperaçãoàs 16:42:301. Restaurarcompleto2. Repetir WAL para atingir3. Banco de dados recuperado!PITR = Restaurar último backup completo + Repetir segmentos WAL/binlog até 1 segundo antes do desastreGranularidade de recuperação: por transação (PostgreSQL WAL) ou por segundo (log binário MySQL)

PITR para PostgreSQL

PostgreSQL PITR funciona restaurando um backup base e reproduzindo segmentos WAL até o carimbo de data/hora de destino. Com o pgBackRest, todo o processo é um único comando.

# Restore to specific point in time with pgBackRest
pgbackrest --stanza=production \
  --type=time --target="2026-04-12 16:42:30" \
  --target-action=promote \
  restore

# Manual PITR using pg_basebackup + WAL archive
# 1. Stop PostgreSQL
systemctl stop postgresql

# 2. Clear the data directory and restore base backup
rm -rf /var/lib/postgresql/16/main/*
tar xzf /backups/pg-base-20260412.tar.gz -C /var/lib/postgresql/16/main/

# 3. Create recovery signal and configure restore
cat > /var/lib/postgresql/16/main/postgresql.auto.conf << 'CONF'
restore_command = 'cp /backup/wal_archive/%f %p'
recovery_target_time = '2026-04-12 16:42:30'
recovery_target_action = 'promote'
CONF
touch /var/lib/postgresql/16/main/recovery.signal

# 4. Start PostgreSQL — it will replay WAL and stop at target
systemctl start postgresql

PITR para MySQL

MySQL PITR combina uma restauração física XtraBackup com reprodução de log binário.

# 1. Restore the XtraBackup
systemctl stop mysqld
rm -rf /var/lib/mysql/*
xtrabackup --prepare --target-dir=/backups/full-20260412
xtrabackup --copy-back --target-dir=/backups/full-20260412
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld

# 2. Identify the binlog position from XtraBackup metadata
cat /backups/full-20260412/xtrabackup_binlog_info
# Output: mysql-bin.000042  154  3E11FA47-1111-1111-1111-AAAAAAAAAAAA:1-1234

# 3. Replay binlogs up to target time
mysqlbinlog --start-position=154 \
  --stop-datetime="2026-04-12 16:42:30" \
  /backup/binlogs/mysql-bin.000042 \
  /backup/binlogs/mysql-bin.000043 | mysql -u root
Arquitetura de backup multinuvem

As estratégias de backup de produção do

devem levar em conta a falha de qualquer provedor de nuvem ou região. Armazenar backups exclusivamente na mesma conta de nuvem e região que seu banco de dados de produção significa que um comprometimento de uma única conta, um problema de faturamento ou uma interrupção regional pode prejudicar seus dados e seus backups simultaneamente. Uma arquitetura robusta envia backups para pelo menos dois destinos de armazenamento independentes com replicação entre regiões.

Arquitetura de backup multinuvemPostgreSQLPrimário + RéplicasMySQLPrimário + RéplicasCamada de criptografiaAES-256-CBCTLS em trânsitoSSE-S3 / SSE-KMSem repousoCriptografia do lado do clientevia pgBackRest/ WAL-GAWS S3eu-west-1 (primário)Ciclo de vida do: IA → GeleiraAzure BlobEuropa Ocidental (primário)Políticas de imutabilidadeArmazenamento em nuvem do Googleeuropa-oeste1 (primário)Nearline → ColdlineS3 entre regiõesus-east-1 (DR)Azure GRSNorte da Europa (DR)GCS Multi-RegiãoMultirregião da UE (DR)Monitoramento e monitoramento de backupAlertandoMétricas Prometheus • Painéis Grafana • Alertas PagerDuty/Slack sobre falha de backup ou limite de idadeSetas sólidas = fluxo de backupSetas tracejadas = replicação entre regiõesCaixa tracejada = limite de criptografiaConfiguração de armazenamento em nuvem

com políticas de ciclo de vida

# AWS S3 lifecycle policy (Terraform)
resource "aws_s3_bucket_lifecycle_configuration" "backup_lifecycle" {
  bucket = aws_s3_bucket.db_backups.id

  rule {
    id     = "backup-tiering"
    status = "Enabled"

    transition {
      days          = 30
      storage_class = "STANDARD_IA"
    }
    transition {
      days          = 90
      storage_class = "GLACIER"
    }
    transition {
      days          = 365
      storage_class = "DEEP_ARCHIVE"
    }
    expiration {
      days = 2555  # 7 years for compliance
    }
  }

  rule {
    id     = "wal-segments"
    status = "Enabled"
    filter {
      prefix = "wal-archive/"
    }
    expiration {
      days = 30
    }
  }
}

# Enable cross-region replication
resource "aws_s3_bucket_replication_configuration" "backup_replication" {
  bucket = aws_s3_bucket.db_backups.id
  role   = aws_iam_role.replication.arn

  rule {
    id     = "cross-region-dr"
    status = "Enabled"
    destination {
      bucket        = aws_s3_bucket.db_backups_dr.arn
      storage_class = "STANDARD_IA"
      encryption_configuration {
        replica_kms_key_id = aws_kms_key.dr_key.arn
      }
    }
    source_selection_criteria {
      sse_kms_encrypted_objects {
        status = "Enabled"
      }
    }
  }
}
# Azure Blob immutability policy (Azure CLI)
az storage container immutability-policy create \
  --account-name prodbackupstorage \
  --container-name pg-backups \
  --period 365 \
  --allow-protected-append-writes true

# GCS lifecycle with nearline transition
gsutil lifecycle set /dev/stdin gs://pg-backups-production << 'JSON'
{
  "rule": [
    {"action": {"type": "SetStorageClass", "storageClass": "NEARLINE"}, "condition": {"age": 30}},
    {"action": {"type": "SetStorageClass", "storageClass": "COLDLINE"}, "condition": {"age": 90}},
    {"action": {"type": "Delete"}, "condition": {"age": 2555}}
  ]
}
JSON
Criptografia e segurança de backup

Os backups

são um alvo de alto valor para invasores. Um backup não criptografado roubado fornece ao invasor uma cópia completa dos seus dados de produção sem a necessidade de violar os sistemas em execução. Cada backup, em trânsito e em repouso, deve ser criptografado.

Criptografia em trânsitosignifica usar TLS para todas as conexões entre o servidor de banco de dados e o destino de backup. Tanto o pgBackRest quanto o XtraBackup transmitem em canais criptografados quando configurados com TLS. Ao enviar para S3, Azure Blob ou GCS, os SDKs do cliente usam HTTPS por padrão.

Criptografia em repouso Opossui duas camadas. A criptografia do lado do servidor (SSE) criptografa os dados depois que eles chegam ao destino de armazenamento — S3 SSE-KMS, criptografia do serviço de armazenamento Azure ou criptografia padrão do GCS. A criptografia do lado do cliente criptografa os dados antes que eles saiam do servidor de banco de dados, garantindo que o provedor de nuvem nunca veja dados em texto simples. pgBackRest e WAL-G oferecem suporte nativo à criptografia do lado do cliente.

# pgBackRest client-side encryption config
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=long_random_passphrase_stored_in_vault

# WAL-G client-side encryption
export WALG_LIBSODIUM_KEY=$(cat /etc/wal-g/encryption.key)
# Or GPG-based
export WALG_GPG_KEY_ID=backup@example.com

# MySQL XtraBackup with encryption
xtrabackup --backup --encrypt=AES256 \
  --encrypt-key-file=/etc/mysql/backup-encryption.key \
  --target-dir=/backups/full-encrypted-$(date +%Y%m%d)

Armazene chaves de criptografia separadamente dos próprios backups. Um gerenciador de segredos como HashiCorp Vault, AWS Secrets Manager ou Azure Key Vault é a abordagem recomendada. Se você armazenar a chave junto com o backup, um invasor que obtiver acesso ao seu armazenamento de backup terá tudo o que precisa.

Agendamento de backup automatizado

Os backups manuais do

não são backups – são aspirações. Os agendamentos de backup devem ser automatizados, monitorados e alertar em caso de falha.

Cron do sistema

para Bare Metal e VMs

# /etc/cron.d/database-backups

# PostgreSQL — pgBackRest
# Full backup every Sunday at 01:00
0 1 * * 0 postgres pgbackrest --stanza=production --type=full backup 2>&1 | logger -t pgbackrest-full

# Differential backup every day at 01:00 (except Sunday)
0 1 * * 1-6 postgres pgbackrest --stanza=production --type=diff backup 2>&1 | logger -t pgbackrest-diff

# MySQL — XtraBackup
# Full backup every Sunday at 02:00
0 2 * * 0 root /usr/local/bin/mysql-backup.sh full 2>&1 | logger -t xtrabackup-full

# Incremental backup every day at 02:00 (except Sunday)
0 2 * * 1-6 root /usr/local/bin/mysql-backup.sh incremental 2>&1 | logger -t xtrabackup-incr

# Backup verification — restore test every Wednesday at 04:00
0 4 * * 3 root /usr/local/bin/verify-backup.sh 2>&1 | logger -t backup-verify

Kubernetes CronJobs

Em ambientes Kubernetes, CronJobs substituem o cron do sistema. Eles oferecem lógica de repetição integrada, controle de simultaneidade e integração com o RBAC do cluster e gerenciamento de segredos.

apiVersion: batch/v1
kind: CronJob
metadata:
  name: pg-backup-full
  namespace: database
spec:
  schedule: "0 1 * * 0"  # Sunday 01:00 UTC
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 4
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 7200  # 2 hour timeout
      template:
        spec:
          serviceAccountName: db-backup
          restartPolicy: OnFailure
          containers:
            - name: pgbackrest
              image: pgbackrest/pgbackrest:2.50
              command:
                - /bin/bash
                - -c
                - |
                  pgbackrest --stanza=production --type=full backup
                  RESULT=$?
                  if [ $RESULT -eq 0 ]; then
                    curl -s -X POST "$SLACK_WEBHOOK" \
                      -d '{"text":"PostgreSQL full backup completed successfully"}'
                  else
                    curl -s -X POST "$SLACK_WEBHOOK" \
                      -d '{"text":"ALERT: PostgreSQL full backup FAILED"}'
                  fi
                  exit $RESULT
              envFrom:
                - secretRef:
                    name: pgbackrest-credentials
                - secretRef:
                    name: slack-webhook
              resources:
                requests:
                  memory: 512Mi
                  cpu: 500m
                limits:
                  memory: 2Gi
                  cpu: "2"
              volumeMounts:
                - name: pgbackrest-config
                  mountPath: /etc/pgbackrest
          volumes:
            - name: pgbackrest-config
              configMap:
                name: pgbackrest-conf
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: pg-backup-diff
  namespace: database
spec:
  schedule: "0 1 * * 1-6"  # Mon-Sat 01:00 UTC
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 7
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 3600
      template:
        spec:
          serviceAccountName: db-backup
          restartPolicy: OnFailure
          containers:
            - name: pgbackrest
              image: pgbackrest/pgbackrest:2.50
              command:
                - /bin/bash
                - -c
                - |
                  pgbackrest --stanza=production --type=diff backup
              envFrom:
                - secretRef:
                    name: pgbackrest-credentials
              resources:
                requests:
                  memory: 256Mi
                  cpu: 250m
                limits:
                  memory: 1Gi
                  cpu: "1"
              volumeMounts:
                - name: pgbackrest-config
                  mountPath: /etc/pgbackrest
          volumes:
            - name: pgbackrest-config
              configMap:
                name: pgbackrest-conf
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: mysql-backup-full
  namespace: database
spec:
  schedule: "0 2 * * 0"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 7200
      template:
        spec:
          serviceAccountName: db-backup
          restartPolicy: OnFailure
          containers:
            - name: xtrabackup
              image: percona/percona-xtrabackup:8.0
              command:
                - /bin/bash
                - -c
                - |
                  xtrabackup --backup --stream=xbstream --compress \
                    --user=$MYSQL_BACKUP_USER \
                    --password=$MYSQL_BACKUP_PASS \
                    --host=mysql-primary.database.svc | \
                    aws s3 cp - s3://$S3_BUCKET/mysql/full-$(date +%Y%m%d).xbstream
              envFrom:
                - secretRef:
                    name: mysql-backup-credentials
                - secretRef:
                    name: aws-credentials
              resources:
                requests:
                  memory: 512Mi
                  cpu: 500m
                limits:
                  memory: 2Gi
                  cpu: "2"
Abordagens de backup nativo

Kubernetes

A execução de bancos de dados no Kubernetes introduz uma nova dimensão à estratégia de backup. Além dos backups de banco de dados em nível de aplicativo, você precisa considerar o backup em nível de cluster (etcd), instantâneos de volumes persistentes e backups gerenciados pelo operador.

Pipeline de backupKubernetesClusterKubernetes (k3s / RKE2)CronJobProgramação: 0 1 * * *Módulo de backuppgBackRest/Contêiner XtraBackupMóduloPostgreSQLRéplica StatefulSet0PVC: pg-dadosMóduloMySQLRéplica StatefulSet0PVC: dados mysqlLonghorn CSIInstantâneos PV+ RéplicasVolumeInstantâneo CRDVeleroBackup em nível de clusteretcd + namespaces + PVsArmazenamento de objetosS3/GCS/Azure Blob/MinIOcriptografado e protegido versionadoCamadas de ciclo de vidahabilitadasBackups de banco de dados+ WALVeleroLonghorn S3 alvoPrometheus + GrafanaMétricas de trabalho de backup + alertasTaxa de sucesso/falha do CronJobCaminho de restauração1. Restauração Velero (cluster)2. pgBackRest/XtraBackup (dados)3. Reversão de instantâneo LonghornProgramadorAgente de backupPostgreSQLMySQLVeleroChifre LongoArmazenamento de objetos

Velero para backup em nível de cluster

Velero faz backup de recursos Kubernetes (implantações, serviços, mapas de configuração, segredos) e volumes persistentes. Ele não substitui backups de banco de dados em nível de aplicativo — ele captura um instantâneo consistente de falhas de PVs, que pode não ser transacionalmente consistente para bancos de dados. Use Velero para recuperação de cluster e ferramentas em nível de aplicativo (pgBackRest, XtraBackup) para recuperação de banco de dados.

# Install Velero with S3 backend
velero install \
  --provider aws \
  --bucket velero-backups \
  --secret-file ./credentials-velero \
  --backup-location-config region=eu-west-1 \
  --snapshot-location-config region=eu-west-1 \
  --use-volume-snapshots=true \
  --plugins velero/velero-plugin-for-aws:v1.9.0

# Create a scheduled backup of the database namespace
velero schedule create db-namespace-backup \
  --schedule="0 3 * * *" \
  --include-namespaces database \
  --ttl 720h \
  --storage-location default \
  --volume-snapshot-locations default

# On-demand backup before maintenance
velero backup create pre-maintenance-$(date +%Y%m%d) \
  --include-namespaces database,monitoring \
  --wait

# Restore a namespace from backup
velero restore create --from-backup pre-maintenance-20260412 \
  --include-namespaces database
Instantâneos do Longhorn

na k3s

As implantações

k3s geralmente usam Longhorn como provedor de armazenamento CSI. O Longhorn fornece snapshots em nível de volume e a capacidade de replicar snapshots para armazenamento de objetos compatível com S3. Para bancos de dados, combine snapshots do Longhorn com backups em nível de aplicativo para defesa profunda.

# Longhorn recurring snapshot job via CRD
apiVersion: longhorn.io/v1beta2
kind: RecurringJob
metadata:
  name: pg-data-snapshot
  namespace: longhorn-system
spec:
  cron: "0 */4 * * *"  # every 4 hours
  task: snapshot
  retain: 6
  concurrency: 1
  groups:
    - pg-data
  labels:
    app: postgresql
---
# Longhorn recurring backup to S3
apiVersion: longhorn.io/v1beta2
kind: RecurringJob
metadata:
  name: pg-data-s3-backup
  namespace: longhorn-system
spec:
  cron: "0 2 * * *"  # daily at 02:00
  task: backup
  retain: 14
  concurrency: 1
  groups:
    - pg-data
  labels:
    app: postgresql
---
# VolumeSnapshot using Longhorn CSI
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: pg-data-snap-$(date +%Y%m%d)
  namespace: database
spec:
  volumeSnapshotClassName: longhorn-snapshot-vsc
  source:
    persistentVolumeClaimName: pg-data-postgresql-0
Backups gerenciados pelo operador

Operadores de banco de dados

como CloudNativePG (para PostgreSQL) e Percona Operator (para MySQL) integram o gerenciamento de backup diretamente no ciclo de vida do banco de dados. O operador lida com agendamento, arquivamento WAL e retenção automaticamente por meio de recursos personalizados.

# CloudNativePG cluster with integrated backup
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: production-pg
  namespace: database
spec:
  instances: 3
  storage:
    size: 100Gi
    storageClass: longhorn
  backup:
    barmanObjectStore:
      destinationPath: s3://pg-backups/cnpg/
      endpointURL: https://s3.eu-west-1.amazonaws.com
      s3Credentials:
        accessKeyId:
          name: aws-creds
          key: ACCESS_KEY_ID
        secretAccessKey:
          name: aws-creds
          key: SECRET_ACCESS_KEY
      wal:
        compression: gzip
        maxParallel: 4
      data:
        compression: gzip
    retentionPolicy: "30d"
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: production-pg-weekly
  namespace: database
spec:
  schedule: "0 1 * * 0"
  backupOwnerReference: self
  cluster:
    name: production-pg
Estratégias específicas do provedor de nuvem

AWS - RDS e Aurora

O

AWS RDS fornece snapshots diários automatizados com retenção configurável (até 35 dias) e backup contínuo por meio de arquivamento de log de transações para recuperação pontual. Aurora adiciona Backtrack, que pode retroceder o cluster para qualquer ponto dentro da janela de retrocesso sem exigir uma restauração – ele simplesmente reverte o estado interno do banco de dados.

# Enable automated backups with maximum retention (Terraform)
resource "aws_db_instance" "production" {
  identifier             = "production-pg"
  engine                 = "postgres"
  engine_version         = "16.2"
  instance_class         = "db.r6g.xlarge"
  allocated_storage      = 500
  backup_retention_period = 35  # maximum
  backup_window          = "03:00-04:00"
  copy_tags_to_snapshot  = true
  deletion_protection    = true
  storage_encrypted      = true
  kms_key_id             = aws_kms_key.rds.arn

  # Enable PITR
  enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"]
}

# Cross-region automated backup replication
resource "aws_db_instance_automated_backups_replication" "dr" {
  source_db_instance_arn = aws_db_instance.production.arn
  kms_key_id             = aws_kms_key.dr_rds.arn
  retention_period       = 14
}

# Aurora Backtrack (MySQL-compatible Aurora only)
resource "aws_rds_cluster" "aurora_production" {
  cluster_identifier      = "aurora-production"
  engine                  = "aurora-mysql"
  engine_version          = "8.0.mysql_aurora.3.05.2"
  backtrack_window        = 86400  # 24 hours of backtrack
  backup_retention_period = 35
  preferred_backup_window = "03:00-04:00"
  storage_encrypted       = true
}

# Manual snapshot with cross-region copy
aws rds create-db-snapshot \
  --db-instance-identifier production-pg \
  --db-snapshot-identifier pre-migration-$(date +%Y%m%d)

aws rds copy-db-snapshot \
  --source-db-snapshot-identifier arn:aws:rds:eu-west-1:123456789:snapshot:pre-migration-20260412 \
  --target-db-snapshot-identifier pre-migration-20260412-dr \
  --source-region eu-west-1 \
  --region us-east-1 \
  --kms-key-id arn:aws:kms:us-east-1:123456789:key/dr-key-id

Azure — Servidor Flexível

O banco de dados

Azure para servidores flexíveis PostgreSQL e MySQL inclui backups automáticos com armazenamento localmente redundante ou com redundância geográfica. O backup com redundância geográfica permite a restauração entre regiões para recuperação de desastres.

# Azure Flexible Server with geo-redundant backup (Terraform)
resource "azurerm_postgresql_flexible_server" "production" {
  name                = "production-pg"
  location            = "westeurope"
  resource_group_name = azurerm_resource_group.db.name
  sku_name            = "GP_Standard_D4s_v3"
  version             = "16"
  storage_mb          = 524288  # 512 GB

  backup_retention_days        = 35
  geo_redundant_backup_enabled = true

  authentication {
    active_directory_auth_enabled = true
    password_auth_enabled         = false
  }
}

# Azure Blob immutability for self-managed backups
resource "azurerm_storage_management_policy" "backup_lifecycle" {
  storage_account_id = azurerm_storage_account.backups.id

  rule {
    name    = "backup-tiering"
    enabled = true
    filters {
      blob_types   = ["blockBlob"]
      prefix_match = ["pg-backups/"]
    }
    actions {
      base_blob {
        tier_to_cool_after_days_since_modification_greater_than    = 30
        tier_to_archive_after_days_since_modification_greater_than = 90
        delete_after_days_since_modification_greater_than          = 2555
      }
    }
  }
}
GCP

— Nuvem SQL

O

Cloud SQL fornece backups automatizados e recuperação pontual prontos para uso. Para bancos de dados autogerenciados no GCE ou GKE, o GCS com classes de armazenamento nearline e coldline oferece armazenamento de backup econômico de longo prazo.

# Cloud SQL with automated backups and PITR (Terraform)
resource "google_sql_database_instance" "production" {
  name             = "production-pg"
  database_version = "POSTGRES_16"
  region           = "europe-west1"

  settings {
    tier = "db-custom-4-16384"

    backup_configuration {
      enabled                        = true
      start_time                     = "03:00"
      point_in_time_recovery_enabled = true
      transaction_log_retention_days = 7
      backup_retention_settings {
        retained_backups = 30
        retention_unit   = "COUNT"
      }
    }

    ip_configuration {
      ssl_mode = "ENCRYPTED_ONLY"
    }
  }
}

# Export to GCS for long-term retention
gcloud sql export sql production-pg \
  gs://pg-backups-longterm/export-$(date +%Y%m%d).sql.gz \
  --database=production_db \
  --offload
Verificação de backup e teste de restauração

Um backup que nunca foi testado não é um backup – é uma esperança. Os testes de restauração automatizados devem ser executados regularmente, de preferência semanalmente, em um ambiente isolado. O teste deve validar não apenas que a restauração foi concluída sem erros, mas também que os dados restaurados são consistentes e que o aplicativo pode conectá-los e consultá-los.

#!/bin/bash
# verify-backup.sh — Automated backup verification script
set -euo pipefail

RESTORE_DIR="/tmp/backup-verify-$(date +%Y%m%d-%H%M%S)"
LOG_FILE="/var/log/backup-verify.log"
SLACK_WEBHOOK="${SLACK_WEBHOOK_URL}"
DB_TYPE="${1:-postgresql}"  # postgresql or mysql

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"; }
alert() {
  log "ALERT: $*"
  curl -s -X POST "$SLACK_WEBHOOK" \
    -H 'Content-Type: application/json' \
    -d "{\"text\":\"BACKUP VERIFY FAILED: $*\"}"
}

cleanup() {
  log "Cleaning up $RESTORE_DIR"
  rm -rf "$RESTORE_DIR"
  if [ "$DB_TYPE" = "postgresql" ]; then
    pg_ctlcluster 16 verify stop 2>/dev/null || true
  else
    mysqladmin -S /tmp/mysql-verify.sock shutdown 2>/dev/null || true
  fi
}
trap cleanup EXIT

mkdir -p "$RESTORE_DIR"

if [ "$DB_TYPE" = "postgresql" ]; then
  log "Starting PostgreSQL backup verification"

  # Restore latest pgBackRest backup to temporary directory
  pgbackrest --stanza=production \
    --pg1-path="$RESTORE_DIR/pgdata" \
    --type=immediate \
    --target-action=promote \
    restore 2>&1 | tee -a "$LOG_FILE"

  if [ ${PIPESTATUS[0]} -ne 0 ]; then
    alert "pgBackRest restore failed"
    exit 1
  fi

  # Start PostgreSQL on a different port
  pg_ctlcluster 16 verify start -- \
    -D "$RESTORE_DIR/pgdata" \
    -o "-p 5433" \
    -o "-c listen_addresses=127.0.0.1"

  sleep 5

  # Verify data integrity
  TABLES=$(psql -p 5433 -d production_db -t -c \
    "SELECT count(*) FROM information_schema.tables WHERE table_schema='public';")
  log "Verified $TABLES tables exist"

  ROW_CHECK=$(psql -p 5433 -d production_db -t -c \
    "SELECT count(*) FROM orders WHERE created_at > now() - interval '7 days';")
  log "Recent orders count: $ROW_CHECK"

  if [ "$ROW_CHECK" -lt 1 ]; then
    alert "PostgreSQL restore has no recent data — possible stale backup"
    exit 1
  fi

  # Run pg_amcheck for corruption detection (PostgreSQL 14+)
  pg_amcheck -p 5433 -d production_db --heapallindexed 2>&1 | tee -a "$LOG_FILE"

  log "PostgreSQL backup verification PASSED"

else
  log "Starting MySQL backup verification"

  # Prepare and restore latest XtraBackup
  LATEST_FULL=$(ls -td /backups/full-* | head -1)
  cp -r "$LATEST_FULL" "$RESTORE_DIR/mysql-data"
  xtrabackup --prepare --target-dir="$RESTORE_DIR/mysql-data"

  # Start MySQL on a different socket and port
  mysqld --datadir="$RESTORE_DIR/mysql-data" \
    --socket=/tmp/mysql-verify.sock \
    --port=3307 \
    --skip-networking=0 \
    --bind-address=127.0.0.1 &

  sleep 10

  # Verify data
  TABLES=$(mysql -S /tmp/mysql-verify.sock -e \
    "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='production_db';" -sN)
  log "Verified $TABLES tables exist"

  mysqlcheck -S /tmp/mysql-verify.sock --all-databases --check 2>&1 | tee -a "$LOG_FILE"

  log "MySQL backup verification PASSED"
fi

curl -s -X POST "$SLACK_WEBHOOK" \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\"Backup verification PASSED for $DB_TYPE at $(date)\"}"

log "Verification complete"
Planejamento de recuperação de desastres

: RTO e RPO

Cada estratégia de backup deve ser projetada em torno de duas métricas:Objetivo de tempo de recuperação (RTO)— quanto tempo você pode ficar inativo — eObjetivo de ponto de recuperação (RPO)— quantos dados você pode perder. Esses números orientam todas as decisões sobre frequência, método e arquitetura de backup.

CenárioRTORPOEstratégia
Check-out de comércio eletrônico< 5 min0 (perda zero de dados)Replicação síncrona + arquivamento WAL contínuo + failover em espera ativa
SaaS aplicação< 30 min< 1 minReplicação de streaming + arquivamento contínuo WAL-G + failover automatizado
Ferramentas internas< 4 horas< 1 horaDiferencial diário + incremental horário + arquivamento WAL
Análise/armazenamento de dados< 24 horas< 24 horasBackup completo diário para armazenamento em nuvem
Desenvolvimento/preparação< 48 horas< 1 semanaBackup completo semanal

Para RPO zero, você precisa de replicação síncrona para pelo menos um modo de espera. Isto adiciona latência a cada transação de gravação, mas garante que nenhuma transação confirmada seja perdida. A maioria dos sistemas de produção aceita RPO (segundos de perda potencial) quase zero usando replicação de streaming assíncrona com arquivamento WAL/binlog contínuo, o que evita a penalidade de latência de gravação.

Modelo de runbook de recuperação de desastres

# DR Runbook: Database Recovery

## Severity Levels
- P1: Complete data loss / corruption — all hands, CEO notified
- P2: Partial data loss / single region down — on-call team + escalation
- P3: Replica failure / backup failure — on-call investigation

## Recovery Procedures

### Scenario A: Primary DB failure, replicas healthy
1. Promote replica to primary (automated via Patroni / orchestrator)
2. Verify application connectivity
3. Re-establish replication from new primary
4. Investigate root cause

### Scenario B: Complete cluster failure, backups intact
1. Provision new database infrastructure
2. Restore latest full backup
3. Apply WAL/binlog to reach latest consistent point
4. Verify data integrity with checksums
5. Update DNS / connection strings
6. Resume application traffic
7. Re-establish backup schedule immediately

### Scenario C: Data corruption (bad migration / SQL injection)
1. Identify exact timestamp of corruption
2. Restore to point-in-time just before corruption
3. Export affected tables from restored copy
4. Merge clean data into production
5. OR: full PITR restore if corruption is widespread

## Contacts
- DBA on-call: [PagerDuty rotation]
- Infrastructure: [PagerDuty rotation]
- VP Engineering: [phone number]

## Validation Checklist
- [ ] Application health checks pass
- [ ] Row counts match expected ranges
- [ ] Recent transactions are present
- [ ] Replication re-established
- [ ] Backup schedule resumed
- [ ] Post-incident review scheduled
Monitoramento e alerta de backup

Os sistemas de backup

falham silenciosamente. O banco de dados continua em execução, o aplicativo continua atendendo ao tráfego e ninguém percebe que os backups pararam de funcionar há três semanas – até que precisem de um. O monitoramento proativo é essencial.

# Prometheus alerting rules for backup monitoring
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: backup-alerts
  namespace: monitoring
spec:
  groups:
    - name: database-backups
      rules:
        - alert: BackupTooOld
          expr: |
            (time() - backup_last_successful_timestamp_seconds) > 90000
          for: 10m
          labels:
            severity: critical
          annotations:
            summary: "Database backup is older than 25 hours"
            description: "Last successful backup for {{ $labels.database }} was {{ $value | humanizeDuration }} ago"

        - alert: BackupJobFailed
          expr: |
            kube_job_status_failed{job_name=~".*backup.*"} > 0
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: "Backup CronJob failed: {{ $labels.job_name }}"

        - alert: WALArchivingLagging
          expr: |
            pg_stat_archiver_failed_count > 0
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "PostgreSQL WAL archiving has failures"

        - alert: BackupStorageQuotaNearing
          expr: |
            (backup_storage_used_bytes / backup_storage_quota_bytes) > 0.85
          for: 30m
          labels:
            severity: warning
          annotations:
            summary: "Backup storage at {{ $value | humanizePercentage }} capacity"

        - alert: BinlogSpaceCritical
          expr: |
            mysql_binlog_size_bytes > 53687091200
          for: 10m
          labels:
            severity: warning
          annotations:
            summary: "MySQL binlog space exceeds 50GB — check archiving"
# Custom Prometheus exporter for pgBackRest metrics
#!/usr/bin/env python3
"""pgBackRest Prometheus exporter — exposes backup age and size metrics."""
import json
import subprocess
import time
from prometheus_client import start_http_server, Gauge

BACKUP_AGE = Gauge('pgbackrest_last_backup_age_seconds', 'Seconds since last backup', ['stanza', 'type'])
BACKUP_SIZE = Gauge('pgbackrest_last_backup_size_bytes', 'Size of last backup', ['stanza', 'type'])
BACKUP_REPO_SIZE = Gauge('pgbackrest_repo_size_bytes', 'Total repository size', ['stanza'])

def collect():
    result = subprocess.run(
        ['pgbackrest', '--output=json', 'info'],
        capture_output=True, text=True
    )
    info = json.loads(result.stdout)
    for stanza_info in info:
        stanza = stanza_info['name']
        for backup in stanza_info.get('backup', []):
            backup_type = backup['type']
            stop_time = backup['timestamp']['stop']
            age = time.time() - stop_time
            BACKUP_AGE.labels(stanza=stanza, type=backup_type).set(age)
            size = backup['info']['size']
            BACKUP_SIZE.labels(stanza=stanza, type=backup_type).set(size)

if __name__ == '__main__':
    start_http_server(9854)
    while True:
        collect()
        time.sleep(300)
Erros comuns e antipadrões do

Depois de gerenciar backups de bancos de dados em dezenas de ambientes de produção, esses são os erros que causam mais danos.

1. Backup no mesmo disco do banco de dados.Se o disco falhar, você perderá o banco de dados e o backup. Sempre grave backups em um destino de armazenamento separado – de preferência fora do host e fora da região.

2. Nunca testando restaurações.Um backup que não pode ser restaurado não é um backup. Agende testes de restauração automatizados semanalmente e peça aos engenheiros que realizem exercícios de restauração manuais trimestralmente.

3. Confiar exclusivamente na replicação como backup. A replicaçãonão é backup. UmDROP TABLEno primário é replicado instantaneamente para todas as réplicas. A replicação protege contra falhas de hardware e não contra erros lógicos.

4. Não monitorando tarefas de backup. As tarefas Cronfalham silenciosamente. Kubernetes CronJobs são suspensos. As credenciais S3 expiram. Cada tarefa de backup deve relatar sucesso ou falha a um sistema de monitoramento e alertar se o backup bem-sucedido mais recente for anterior ao seu RPO.

5. Armazenar chaves de criptografia juntamente com backups.Se um invasor obtiver acesso ao seu armazenamento de backup, ele também não deverá ter a chave de descriptografia. Armazene as chaves em um gerenciador de segredos dedicado.

6. Nenhuma política de retenção.Sem políticas de ciclo de vida, o armazenamento de backup cresce ilimitadamente. Defina janelas de retenção claras: 7 dias para segmentos WAL, 30 dias para backups diários, 12 meses para backups mensais e automatize sua exclusão.

7. Ignorando o impacto no desempenho do backup.A execução de um backup completo em um banco de dados primário durante horários de pico degrada o desempenho do aplicativo. Agende backups durante janelas de baixo tráfego ou faça backup a partir de uma réplica dedicada.

8. Usandomysqldumppara bancos de dados grandes sem--single-transaction.Sem esse sinalizador, omysqldumpbloqueia tabelas, bloqueando gravações durante o dump. Para bancos de dados grandes, isso pode significar minutos ou horas de inatividade.

9. Esquecendo de fazer backup da configuração do banco de dados.Restaurar dados é apenas metade da batalha. Se você perderpostgresql.conf,pg_hba.conf,my.cnf, configurações de replicação e concessões de usuário, não será possível trazer o banco de dados de volta a um estado utilizável. Inclua arquivos de configuração em seu processo de backup.

10. Não documentando o procedimento de restauração.Durante uma interrupção, a pessoa que restaura o banco de dados pode não ser a pessoa que configurou os backups. Um runbook escrito e testado é fundamental.

Otimização de custos do

para armazenamento de backup

Os custos de armazenamento de backup do

podem crescer rapidamente, especialmente com backups completos frequentes de grandes bancos de dados. Estas estratégias mantêm os custos sob controlo sem comprometer a recuperabilidade.

Use backups incrementais/diferenciais.Um backup completo semanal mais diferenciais diários usa uma fração do armazenamento em comparação com backups completos diários. A capacidade de restauração delta do pgBackRest significa que backups incrementais são restaurados quase tão rápido quanto backups completos.

Ativa a compactação.Algoritmos de compactação modernos como o zstd oferecem excelentes taxas de compactação (5:1 a 10:1 para dados típicos de banco de dados) com sobrecarga mínima do CPU. Tanto o pgBackRest quanto o XtraBackup suportam zstd nativamente.

Implementar camadas de armazenamento.Mova os backups para níveis de armazenamento cada vez mais baratos à medida que envelhecem. As políticas de ciclo de vida mostradas anteriormente (S3 Standard → IA → Glacier, GCS Standard → Nearline → Coldline) podem reduzir os custos de armazenamento de longo prazo em 70–90%.

Desduplicar sempre que possível.pgBackRest usa desduplicação em nível de bloco em seu repositório, armazenando apenas blocos alterados em backups. Isso reduz drasticamente o armazenamento de bancos de dados onde a maioria dos dados é estática.

Janelas de retenção do tamanho certo.Muitas equipes optam por manter backups para sempre por precaução. Analise seus padrões reais de recuperação e requisitos de conformidade e defina a retenção correspondente. Um requisito de retenção de 7 anos pode usar armazenamento de arquivo profundo por menos de US$ 1/TB/mês na maioria dos provedores de nuvem.

# Cost comparison: Full vs Incremental backup storage
# Assuming 500 GB database, 5% daily change rate, 30-day retention

# Strategy A: Daily full backups
# 500 GB × 30 days = 15,000 GB = 15 TB
# S3 Standard: 15 TB × $0.023/GB = $345/month

# Strategy B: Weekly full + daily incremental
# 4 full × 500 GB = 2,000 GB
# 26 incremental × 25 GB = 650 GB
# Total: 2,650 GB ≈ 2.6 TB
# S3 Standard: 2.6 TB × $0.023/GB = $59.80/month

# Strategy C: Strategy B + lifecycle tiering
# Current week: 525 GB Standard = $12.08
# Weeks 2-4: 2,125 GB Standard-IA = $26.56
# Total: $38.64/month

# Savings: Strategy C is 89% cheaper than Strategy A

Juntando tudo: uma arquitetura de backup completa

Esta é a arquitetura de backup recomendada para um ambiente de produção executando MySQL e PostgreSQL, implantado em Kubernetes com recuperação de desastres em várias nuvens.

Para PostgreSQL:

  • pgBackRest como ferramenta de backup primária com dois repositórios (S3 + Azure Blob)
  • Arquivamento WAL contínuo em ambos os repositórios
  • Backup completo semanal + diferencial diário (via K8s CronJob)
  • Capturas instantâneas de volume do Longhorn a cada 4 horas para reversão rápida
  • Verificação de restauração automatizada toda quarta-feira
  • Monitoramento
  • Prometheus com alertas sobre idade de backup, falha e armazenamento

Para MySQL:

  • Percona XtraBackup para backups físicos transmitidos para S3
  • Envio contínuo de log binário para armazenamento separado
  • Completo semanal + incremental diário (via K8s CronJob)
  • Diáriomysqldumpde esquemas críticos para backups lógicos portáteis
  • Instantâneos de volume do Longhorn
  • a cada 4 horas
  • Verificação de restauração automatizada toda quinta-feira

Para o cluster Kubernetes:

  • Velero backup diário de namespaces de banco de dados com instantâneos PV
  • Instantâneos do
  • RKE2/k3s etcd a cada 6 horas para armazenamento fora do cluster
  • Repositório
  • GitOps como fonte da verdade para todos os manifestos

Para recuperação de desastres:

    Replicação entre regiões
  • S3 para região DR
  • Azure GRS para cópias de backup com redundância geográfica
  • Drill mensal de DR
  • : reconstrução completa do cluster a partir de backups na região de DR
  • Runbook documentado com árvore de decisão para cada cenário de falha
Conclusão

Os backups de banco de dados

são a última linha de defesa entre o seu negócio e a perda catastrófica de dados. As estratégias descritas neste artigo — backups físicos e lógicos, arquivamento WAL contínuo e binlog, armazenamento em várias nuvens com políticas de ciclo de vida, criptografia em todas as camadas, agendamento automatizado via Kubernetes CronJobs e verificação sistemática de restauração — representam o estado da arte atual para ambientes de produção MySQL e PostgreSQL.

A conclusão mais importante é esta:uma estratégia de backup é tão boa quanto seu último teste de restauração bem-sucedido. Cada ferramenta, script e padrão de arquitetura neste artigo existe para servir a um propósito: garantir que, quando o pior acontecer, você possa recuperar seus dados, cumprir seus compromissos de RTO e RPO e manter seu negócio funcionando. Construa seu sistema de backup, automatize-o, monitore-o, teste-o e teste-o novamente. Seu eu futuro agradecerá.