Skip to content

Database Backup


Backups are your last line of defense against data loss. Whether from hardware failure, human error, or ransomware, you need tested backups to recover. As a DevOps/SRE, you’ll design backup strategies, automate backups, and most importantly - regularly test restores.

┌─────────────────────────────────────────────────────────────────────────────┐
│ BACKUP STRATEGY IN DEVOPS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ THE 3-2-1 BACKUP RULE │ │
│ │ │ │
│ │ 3 copies of data │ │
│ │ 2 different media types │ │
│ │ 1 offsite backup │ │
│ │ │ │
│ │ Example: │ │
│ │ • Primary DB │ │
│ │ • Local backup (disk) │ │
│ │ • Remote backup (S3/Glacier) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ BACKUP TYPES │ │
│ │ │ │
│ │ Full: Complete database copy │ │
│ │ Incremental: Changes since last backup │ │
│ │ Differential: Changes since last full backup │ │
│ │ Point-in-time: Recovery to specific timestamp │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ CRITICAL: TEST RESTORES! │ │
│ │ │ │
│ │ A backup that can't be restored is worthless! │ │
│ │ │ │
│ │ • Weekly restore tests in staging │ │
│ │ • Document restore procedures │ │
│ │ • Measure time to restore │ │
│ │ • Test partial restores (specific tables) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Real-world scenarios:

  • Ransomware recovery: Restore from clean backup before attack
  • Accidental deletion: Point-in-time recovery to before deletion
  • Schema migration failure: Restore to previous state
  • Hardware failure: Bring up DB on new hardware from backup

Terminal window
# Full backup
mysqldump -u root -p --all-databases > full_backup.sql
# Single database
mysqldump -u root -p mydb > mydb.sql
# Multiple databases
mysqldump -u root -p --databases db1 db2 db3 > backup.sql
# With options
mysqldump -u root -p \
--single-transaction \
--routines \
--triggers \
--events \
mydb > mydb.sql
# Quick backup (no locks)
mysqldump -u root -p --single-transaction --quick mydb > backup.sql
# Lock tables (for MyISAM)
mysqldump -u root -p --lock-tables mydb > backup.sql
# Compressed backup
mysqldump -u root -p mydb | gzip > backup.sql.gz
# Partial backup (only tables)
mysqldump -u root -p mydb table1 table2 > tables.sql
Terminal window
# Restore database
mysql -u root -p mydb < backup.sql
# Restore compressed
gunzip < backup.sql.gz | mysql -u root -p
# Restore to different database
mysql -u root -p newdb < backup.sql
# Execute SQL directly
mysql -u root -p -e "source backup.sql"
Terminal window
# Using xtrabackup (Percona)
# Install
sudo apt install percona-xtrabackup
# Full backup
xtrabackup --backup --target-dir=/backup/full --user=root --password=root
# Prepare backup
xtrabackup --prepare --target-dir=/backup/full
# Restore
xtrabackup --copy-back --target-dir=/backup/full
# Incremental backup
xtrabackup --backup --target-dir=/backup/inc1 --incremental-basedir=/backup/full
# Stream backup
xtrabackup --backup --stream=tar | gzip > backup.tar.gz

Terminal window
# Plain SQL backup
pg_dump -U user mydb > backup.sql
pg_dump -U user mydb -f backup.sql
# Custom format (compressed)
pg_dump -U user -Fc mydb > backup.dump
# Directory format (parallel)
pg_dump -U user -Fd mydb -f backup_dir
# Only schema
pg_dump -U user --schema-only mydb > schema.sql
# Only data
pg_dump -U user --data-only mydb > data.sql
# Compressed
pg_dump -U user mydb | gzip > backup.sql.gz
Terminal window
# Plain SQL restore
psql -U user mydb < backup.sql
# Custom format restore
pg_restore -U user -d mydb backup.dump
# Restore to different database
createdb -U user newdb
pg_restore -U user -d newdb backup.dump
# Restore specific table
pg_restore -U user -d mydb --data-only --table=mytable backup.dump
Terminal window
# Full base backup
pg_basebackup -h localhost -U replicator -D /backup/base -P -Xs
# With tar format
pg_basebackup -h localhost -U replicator -D /backup -Ft -z -P
# With replication slot
pg_basebackup -h master -D /backup -U replicator -P --slot=replica_slot

/usr/local/bin/db-backup.sh
#!/bin/bash
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="mydb"
DB_USER="backup"
DB_PASS="password"
# MySQL backup
mysqldump -u $DB_USER -p$DB_PASS --single-transaction \
--routines --triggers $DB_NAME | gzip > \
$BACKUP_DIR/mysql_${DB_NAME}_${DATE}.sql.gz
# PostgreSQL backup
pg_dump -U $DB_USER -Fc $DB_NAME | gzip > \
$BACKUP_DIR/pg_${DB_NAME}_${DATE}.dump.gz
# Keep only 7 days
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
find $BACKUP_DIR -name "*.dump.gz" -mtime +7 -delete
# Log
echo "Backup completed: $DATE" >> /var/log/backup.log
/etc/cron.d/database-backup
# Daily at 2 AM
0 2 * * * root /usr/local/bin/db-backup.sh
# Every 6 hours
# 0 */6 * * * root /usr/local/bin/db-backup.sh

  1. What is mysqldump?

    • MySQL logical backup tool
  2. What’s the difference between pg_dump and pg_basebackup?

    • pg_dump: logical (SQL), pg_basebackup: physical
  3. What does —single-transaction do?

    • Wraps dump in transaction for consistent backup
  4. What is point-in-time recovery?

    • Restoring to specific point using WAL
  5. How do you automate backups?

    • Cron jobs with backup scripts

❌ WRONG: Assuming backups work without testing

Terminal window
# Just assuming backup is good
mysqldump -u root -p db > backup.sql
# Never restore to verify!

✅ CORRECT: Regular restore testing

#!/bin/bash
# Test restore weekly
mysql -u root -p test_restore < backup.sql
# Verify data integrity

❌ WRONG: Backups only on same server

Terminal window
# Local backup only
mysqldump db > /backup/db.sql
# If server fails, backups lost!

✅ CORRECT: Offsite backup

Terminal window
# Backup to local + remote
mysqldump db > /backup/db.sql
aws s3 cp /backup/db.sql s3://bucket/backups/

❌ WRONG: Backup impacts production performance

Terminal window
# Running during business hours
0 14 * * * mysqldump db > backup.sql # 2 PM - peak time

✅ CORRECT: Schedule during off-peak

Terminal window
# Run at 3 AM
0 3 * * * mysqldump --single-transaction db > backup.sql

❌ WRONG: Sensitive data in plain text

Terminal window
# Plain text backup
mysqldump db > backup.sql
# Anyone with access can read sensitive data!

✅ CORRECT: Encrypt backups

Terminal window
# Encrypted backup
mysqldump db | gpg -c > backup.sql.gpg
# Or use mysqldump with --set-gtid-purged

❌ WRONG: Keeping backups forever, filling disk

Terminal window
# No cleanup
mysqldump db > backup_$(date +%Y%m%d).sql
# Disk will fill up!

✅ CORRECT: Retention policy

Terminal window
# Keep 7 days locally, 30 days in S3
0 3 * * * mysqldump db > /backup/db_$(date +%Y%m%d).sql
find /backup -name "db_*.sql" -mtime +7 -delete
aws s3 sync /backup s3://bucket/ --delete

Quick Reference
+------------------------------------------------------------------+
| |
| MySQL: |
| +----------------------------------------------------------+ |
| | mysqldump -u user -p db > backup.sql | |
| | mysql -u user -p db < backup.sql | |
| | xtrabackup --backup --target-dir=/backup | |
| +----------------------------------------------------------+ |
| |
| PostgreSQL: |
| +----------------------------------------------------------+ |
| | pg_dump -U user db > backup.sql | |
| | psql -U user db < backup.sql | |
| | pg_basebackup -D /backup | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+