Proč je záloha databází specifická?
Zálohování databáze není totéž jako kopírování souborů. Databáze jsou živé systémy, které neustále zapisují data do datových souborů, transakčních logů a cache. Prostá kopie souborů databáze za běhu vede téměř jistě k poškozené, nekonzistentní záloze.
Správná záloha databáze musí zajistit:
- Konzistenci -- všechny tabulky a relace musí být v konzistentním stavu
- Úplnost -- žádná rozpracovaná transakce nesmí být zachycena částečně
- Obnovitelnost -- záloha musí být úspěšně obnovitelná (nestačí ji vytvořit, musíte ji ověřit)
- Minimální dopad na provoz -- záloha by neměla výrazně zpomalovat produkční databázi
Logické vs. fyzické zálohy
Existují dva fundamentálně odlišné přístupy k zálohování databází:
Logická záloha
Exportuje data ve formátu SQL příkazů (CREATE TABLE, INSERT) nebo jiném textovém formátu. Nástroje: mysqldump, pg_dump, mongodump.
- Přenositelnost mezi verzemi a platformami
- Možnost selektivní obnovy (jedna tabulka)
- Čitelný formát (SQL text)
- Nezávislost na úložišti
Výhody
- Pomalé pro velké databáze (GB-TB)
- Vyšší zátěž na databázový server
- Obnova trvá dlouho (replayování SQL)
- Záloha může být nekonzistentní bez zámků
Nevýhody
Fyzická záloha
Kopíruje datové soubory databáze na binární úrovni. Nástroje: xtrabackup (MySQL), pg_basebackup (PostgreSQL), LVM snapshot, filesystem snapshot.
- Velmi rychlá záloha i obnova
- Minimální zátěž na server
- Konzistentní bez zámků (u moderních nástrojů)
- Podpora inkrementálních záloh
Výhody
- Závislost na verzi a platformě databáze
- Nelze selektivně obnovit jednu tabulku
- Větší velikost zálohy
- Složitější správa
Nevýhody
Hot vs. cold zálohy
Hot backup (online záloha) probíhá za běhu databáze, bez nutnosti ji zastavit. Uživatelé mohou dále číst i zapisovat. Moderní nástroje (xtrabackup, pg_basebackup) toto podporují.
Cold backup (offline záloha) vyžaduje zastavení databáze. Zaručuje 100% konzistenci, ale způsobuje výpadek. V produkčním prostředí je obvykle nepřijatelná.
MySQL / MariaDB
mysqldump
Základní logický zálohovací nástroj dodávaný s MySQL. Exportuje data jako SQL příkazy:
# Záloha jedné databáze
mysqldump -u root -p --single-transaction --routines --triggers \
--databases mydb > /backup/mydb_$(date +%F_%H%M).sql
# Záloha všech databází
mysqldump -u root -p --single-transaction --all-databases \
--routines --triggers --events > /backup/all_$(date +%F).sql
# Záloha s kompresí
mysqldump -u root -p --single-transaction --databases mydb | \
gzip > /backup/mydb_$(date +%F).sql.gz
# Obnova
mysql -u root -p mydb < /backup/mydb_2025-01-15_0200.sql
# Obnova z komprimované zálohy
gunzip < /backup/mydb_2025-01-15.sql.gz | mysql -u root -p mydb
Klíčové parametry:
--single-transaction-- konzistentní záloha InnoDB tabulek bez zámků (používá MVCC snapshot)--routines-- zahrne uložené procedury a funkce--triggers-- zahrne triggery--events-- zahrne naplánované události--master-data=2-- zapíše pozici v binary logu (pro replikaci a PITR)
--single-transaction funguje pouze s InnoDB enginem. Pro MyISAM tabulky je nutné použít --lock-all-tables, což zablokuje zápisy po dobu zálohy. Pokud to je možné, migrujte MyISAM tabulky na InnoDB.
mysqlpump
Vylepšená verze mysqldump dostupná od MySQL 5.7. Hlavní výhoda je paralelní export -- může využívat více vláken pro rychlejší zálohu:
# Paralelní záloha s 4 vlákny
mysqlpump -u root -p --default-parallelism=4 \
--databases mydb > /backup/mydb_pump_$(date +%F).sql
Percona XtraBackup
XtraBackup je nejpoužívanější nástroj pro fyzické zálohy MySQL/MariaDB. Vytváří hot backup bez zámků a podporuje inkrementální zálohy:
# Full backup
xtrabackup --backup --target-dir=/backup/full_$(date +%F) \
--user=root --password=heslo
# Inkrementální backup (na základě předchozí full zálohy)
xtrabackup --backup --target-dir=/backup/inc_$(date +%F) \
--incremental-basedir=/backup/full_2025-01-15 \
--user=root --password=heslo
# Příprava zálohy pro obnovu (apply log)
xtrabackup --prepare --target-dir=/backup/full_2025-01-15
# Příprava s inkrementální zálohou
xtrabackup --prepare --target-dir=/backup/full_2025-01-15 \
--incremental-dir=/backup/inc_2025-01-16
# Obnova (databáze musí být zastavena)
systemctl stop mysql
xtrabackup --copy-back --target-dir=/backup/full_2025-01-15
chown -R mysql:mysql /var/lib/mysql
systemctl start mysql
Point-in-Time Recovery (MySQL)
PITR umožňuje obnovit databázi k libovolnému bodu v čase. Vyžaduje:
- Povolenou binární log replikaci (
log-binv my.cnf) - Pravidelnou full zálohu (mysqldump s
--master-datanebo xtrabackup) - Uchování binary logů mezi zálohami
# Konfigurace v my.cnf
[mysqld]
log-bin = /var/log/mysql/mysql-bin
binlog_format = ROW
expire_logs_days = 14
server-id = 1
# Obnova k bodu v čase
# 1. Obnovte poslední full backup
# 2. Aplikujte binary logy od zálohy do požadovaného času
mysqlbinlog --start-position=4 --stop-datetime="2025-01-16 14:30:00" \
/var/log/mysql/mysql-bin.000042 \
/var/log/mysql/mysql-bin.000043 | mysql -u root -p
PostgreSQL
pg_dump
Logický zálohovací nástroj PostgreSQL. Na rozdíl od mysqldump vytváří konzistentní snapshot bez zámků standardně (díky MVCC):
# Záloha jedné databáze (SQL formát)
pg_dump -U postgres -d mydb -F p -f /backup/mydb_$(date +%F).sql
# Záloha v custom formátu (komprimovaný, paralelní obnova)
pg_dump -U postgres -d mydb -F c -f /backup/mydb_$(date +%F).dump
# Záloha v directory formátu (paralelní záloha i obnova)
pg_dump -U postgres -d mydb -F d -j 4 -f /backup/mydb_$(date +%F)/
# Záloha všech databází
pg_dumpall -U postgres -f /backup/all_$(date +%F).sql
# Obnova z custom formátu
pg_restore -U postgres -d mydb -j 4 /backup/mydb_2025-01-15.dump
# Obnova s vytvořením databáze
pg_restore -U postgres -C -d postgres /backup/mydb_2025-01-15.dump
Klíčové formáty:
-F p(plain) -- čistý SQL text, obnovitelný přespsql-F c(custom) -- komprimovaný binární formát, podpora selektivní a paralelní obnovy přespg_restore-F d(directory) -- každá tabulka v samostatném souboru, podpora paralelní zálohy (-j)-F t(tar) -- tar archiv, kompatibilní spg_restore
pg_basebackup
Fyzická záloha celého PostgreSQL clusteru. Nezbytná pro nastavení WAL archivace a PITR:
# Fyzická záloha celého clusteru
pg_basebackup -U replicator -D /backup/pg_base_$(date +%F) \
-Ft -z -P -R --checkpoint=fast
# Parametry:
# -Ft -- tar formát
# -z -- gzip komprese
# -P -- progress reporting
# -R -- vytvoří standby.signal a recovery konfiguraci
# --checkpoint=fast -- neprodlužuje zálohu čekáním na checkpoint
WAL archivace a PITR (PostgreSQL)
WAL (Write-Ahead Log) je transakční log PostgreSQL. Archivací WAL souborů v kombinaci s pg_basebackup získáte možnost PITR:
# Konfigurace v postgresql.conf
wal_level = replica
archive_mode = on
archive_command = 'cp %p /backup/wal_archive/%f'
# nebo pro vzdálené úložiště:
# archive_command = 'aws s3 cp %p s3://pg-wal-archive/%f'
# Obnova k bodu v čase
# 1. Zastavte PostgreSQL
# 2. Obnovte base backup do datového adresáře
# 3. Vytvořte recovery konfiguraci
# V postgresql.conf (PostgreSQL 12+):
restore_command = 'cp /backup/wal_archive/%f %p'
recovery_target_time = '2025-01-16 14:30:00'
recovery_target_action = 'promote'
# 4. Vytvořte soubor recovery.signal
touch /var/lib/postgresql/16/main/recovery.signal
# 5. Spusťte PostgreSQL -- automaticky provede PITR
systemctl start postgresql
# pgBackRest konfigurace (/etc/pgbackrest/pgbackrest.conf)
[mydb]
pg1-path=/var/lib/postgresql/16/main
[global]
repo1-path=/backup/pgbackrest
repo1-retention-full=4
repo1-retention-diff=7
compress-type=zst
# Full backup
pgbackrest --stanza=mydb backup --type=full
# Diferenciální backup
pgbackrest --stanza=mydb backup --type=diff
# Inkrementální backup
pgbackrest --stanza=mydb backup --type=incr
# Obnova k bodu v čase
pgbackrest --stanza=mydb restore --type=time \
--target="2025-01-16 14:30:00+01"
# Ověření zálohy
pgbackrest --stanza=mydb verify
MongoDB
MongoDB nabízí několik přístupů k zálohování:
mongodump / mongorestore
# Záloha celé instance
mongodump --uri="mongodb://localhost:27017" --out=/backup/mongo_$(date +%F)
# Záloha jedné databáze
mongodump --db=mydb --out=/backup/mongo_$(date +%F)
# Záloha s kompresí
mongodump --db=mydb --gzip --out=/backup/mongo_$(date +%F)
# Obnova
mongorestore --db=mydb /backup/mongo_2025-01-15/mydb/
# Obnova s drop (přepíše existující data)
mongorestore --db=mydb --drop /backup/mongo_2025-01-15/mydb/
MongoDB Atlas Backup
Pokud používáte MongoDB Atlas (managed cloud), máte k dispozici automatické continuous backups s možností PITR. Atlas pořizuje snapshoty každých 6 hodin a uchovává oplog pro PITR v rozmezí posledních 24 hodin (nebo déle u vyšších plánů).
Filesystem snapshoty pro MongoDB
Pro velké MongoDB instance je efektivnější použít filesystem snapshot (LVM, ZFS, EBS snapshot) místo mongodump:
# MongoDB s WiredTiger enginem -- filesystem snapshot je konzistentní
# 1. Zamkněte databázi
mongosh --eval "db.fsyncLock()"
# 2. Vytvořte snapshot (příklad pro LVM)
lvcreate -L 10G -s -n mongo_snap /dev/vg_data/lv_mongo
# 3. Odemkněte databázi
mongosh --eval "db.fsyncUnlock()"
# 4. Záloha ze snapshotu
mount /dev/vg_data/mongo_snap /mnt/snapshot
cp -a /mnt/snapshot/mongodb/ /backup/mongo_snap_$(date +%F)/
umount /mnt/snapshot
lvremove /dev/vg_data/mongo_snap
Plánování a automatizace záloh
Zálohy databází by měly být plně automatizované. Nikdy se nespoléhejte na manuální spouštění.
# Cron job pro denní zálohu MySQL (02:00)
0 2 * * * /usr/local/bin/backup-mysql.sh >> /var/log/backup-mysql.log 2>&1
# Příklad backup skriptu
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/backup/mysql"
DATE=$(date +%F_%H%M)
RETENTION_DAYS=30
# Vytvoření zálohy
mysqldump -u backup_user --single-transaction \
--all-databases --routines --triggers --events | \
gzip > "${BACKUP_DIR}/all_${DATE}.sql.gz"
# Ověření (kontrola, že soubor není prázdný a je validní gzip)
if ! gzip -t "${BACKUP_DIR}/all_${DATE}.sql.gz" 2>/dev/null; then
echo "ERROR: Záloha je poškozená!" >&2
exit 1
fi
# Smazání starých záloh
find "${BACKUP_DIR}" -name "*.sql.gz" -mtime +${RETENTION_DAYS} -delete
echo "OK: Záloha ${DATE} dokončena, velikost: $(du -h ${BACKUP_DIR}/all_${DATE}.sql.gz | cut -f1)"
Ověřování záloh
Záloha, kterou jste netestovali, je jen přání. Automatizujte ověřování:
- Kontrola integrity -- ověřte, že soubor zálohy není poškozený (gzip -t, pg_restore --list)
- Testovací obnova -- pravidelně obnovujte zálohu do testovací instance
- Kontrola dat -- po obnově ověřte počty záznamů, kontrolní součty kritických tabulek
- Monitoring -- nastavte alerty na neúspěšné zálohy a na zálohy, které se neuskutečnily
# Automatické ověření zálohy PostgreSQL
# Obnovení do dočasné databáze a kontrola
createdb -U postgres test_restore
pg_restore -U postgres -d test_restore /backup/mydb_2025-01-15.dump
# Kontrola počtu záznamů
psql -U postgres -d test_restore -c "SELECT count(*) FROM users;"
psql -U postgres -d test_restore -c "SELECT count(*) FROM orders;"
# Úklid
dropdb -U postgres test_restore
Doporučené postupy
- Kombinujte logické a fyzické zálohy -- logické pro flexibilitu, fyzické pro rychlost
- Nastavte PITR -- binary logy (MySQL) nebo WAL archivace (PostgreSQL) umožňují obnovu k libovolnému bodu v čase
- Zálohujte na oddělené úložiště -- zálohy by neměly být na stejném disku jako databáze
- Šifrujte zálohy -- databáze obsahují citlivá data, zálohy musí být chráněny
- Dokumentujte postup obnovy -- v krizi nemáte čas experimentovat
- Monitorujte velikost a trvání záloh -- neočekávané změny mohou indikovat problém
- Oddělte zálohovací přístupy -- zálohovací uživatel by měl mít minimální práva (SELECT, RELOAD, LOCK TABLES, REPLICATION CLIENT)
- Testujte obnovu pravidelně -- automatizovaná měsíční obnova do testovací instance
Závěr
Záloha databází vyžaduje specifický přístup odlišný od zálohování souborů. Klíčem je porozumět rozdílu mezi logickými a fyzickými zálohami, nastavit PITR pro možnost obnovy k libovolnému bodu v čase a pravidelně ověřovat obnovitelnost záloh. Pro MySQL doporučujeme kombinaci mysqldump (malé databáze) a Percona XtraBackup (velké databáze). Pro PostgreSQL je ideální kombinace pg_dump, pg_basebackup a WAL archivace -- nebo komplexní řešení pgBackRest.