 Autor: [Adam Nadolny](/autorzy/adam-nadolny) Ekspert DevOps i infrastruktury · Zweryfikowano Kwiecień 2026

1.  [Strona główna](/) ›
2.  [Baza wiedzy](/baza-wiedzy/) ›
3.  MySQL backup — automatyzacja

# MySQL backup — automatyzacja i rotacja kopii zapasowych

Opublikowano: 9 kwietnia 2026 · Kategoria: Bazy danych

Backup bazy danych to nie jednorazowe zadanie — to proces, który musi działać automatycznie, być weryfikowany i przechowywany poza serwerem głównym. Ten artykuł pokazuje jak zbudować kompletny system backupu MySQL: od mysqldump przez rotację, upload do S3/Backblaze B2, po monitoring i testowanie przywracania.

## mysqldump — podstawy i ważne opcje

`mysqldump` to standardowe narzędzie do tworzenia logicznych kopii baz MySQL/MariaDB. Generuje plik SQL z instrukcjami CREATE TABLE i INSERT, który można przywrócić na dowolnym serwerze z kompatybilną wersją MySQL.

\# Backup jednej bazy danych (InnoDB — bez blokowania tabel)
mysqldump \\
  --single-transaction \\
  --quick \\
  --lock-tables=false \\
  -u root -p nazwa\_bazy > /backup/nazwa\_bazy.sql

# Backup wszystkich baz danych
mysqldump \\
  --single-transaction \\
  --all-databases \\
  --events \\
  --routines \\
  --triggers \\
  -u root -p > /backup/all\_databases.sql

# Backup z natychmiastową kompresją (pipe do gzip)
mysqldump --single-transaction -u root -p nazwa\_bazy | gzip > /backup/nazwa\_bazy.sql.gz

# Przywracanie z pliku SQL
mysql -u root -p nazwa\_bazy < /backup/nazwa\_bazy.sql

# Przywracanie z archiwum gzip
gunzip < /backup/nazwa\_bazy.sql.gz | mysql -u root -p nazwa\_bazy

**Tip:** Utwórz dedykowanego użytkownika MySQL tylko do backupów z minimalnymi uprawnieniami: `GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON *.* TO 'backup_user'@'localhost' IDENTIFIED BY 'haslo';` — przechowuj dane logowania w pliku `~/.my.cnf` aby uniknąć hasła w skrypcie.

## Skrypt backup z rotacją 7/4/12

Standardowa strategia rotacji to: 7 backupów dziennych, 4 tygodniowe, 12 miesięcznych. Poniższy skrypt implementuje tę strategię w Bashu:

#!/bin/bash
# /usr/local/bin/mysql-backup.sh
# Backup MySQL z rotacją 7/4/12 i powiadomieniem email

set -euo pipefail

# --- KONFIGURACJA ---
DB\_USER="backup\_user"
DB\_PASS="twoje\_haslo"
BACKUP\_DIR="/backup/mysql"
LOG\_FILE="/var/log/mysql-backup.log"
ALERT\_EMAIL="admin@example.com"
KEEP\_DAILY=7
KEEP\_WEEKLY=4
KEEP\_MONTHLY=12

# --- FUNKCJE ---
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG\_FILE"
}

alert() {
    echo "$1" | mail -s "BACKUP ERROR: MySQL backup failed" "$ALERT\_EMAIL"
}

# --- GŁÓWNA LOGIKA ---
TODAY=$(date +%Y-%m-%d)
DAY\_OF\_WEEK=$(date +%u)   # 1=Pon, 7=Nie
DAY\_OF\_MONTH=$(date +%d)

mkdir -p "$BACKUP\_DIR"/{daily,weekly,monthly}

log "Starting MySQL backup..."

# Lista baz danych (pomiń systemowe)
DATABASES=$(mysql -u"$DB\_USER" -p"$DB\_PASS" -e "SHOW DATABASES;" 2>/dev/null | \\
    grep -Ev "(Database|information\_schema|performance\_schema|sys)")

# Backup każdej bazy
for DB in $DATABASES; do
    FILENAME="${DB}\_${TODAY}.sql.gz"

    log "Dumping: $DB"
    mysqldump \\
        --single-transaction \\
        --quick \\
        --lock-tables=false \\
        -u"$DB\_USER" -p"$DB\_PASS" \\
        "$DB" 2>/dev/null | gzip > "$BACKUP\_DIR/daily/$FILENAME"

    # Tygodniowy (każda niedziela)
    if \[ "$DAY\_OF\_WEEK" -eq 7 \]; then
        cp "$BACKUP\_DIR/daily/$FILENAME" "$BACKUP\_DIR/weekly/$FILENAME"
        log "Weekly backup saved: $FILENAME"
    fi

    # Miesięczny (1. dzień miesiąca)
    if \[ "$DAY\_OF\_MONTH" -eq "01" \]; then
        cp "$BACKUP\_DIR/daily/$FILENAME" "$BACKUP\_DIR/monthly/$FILENAME"
        log "Monthly backup saved: $FILENAME"
    fi
done

# Rotacja: usuń stare backupy
find "$BACKUP\_DIR/daily"   -name "\*.sql.gz" -mtime +"$KEEP\_DAILY"   -delete
find "$BACKUP\_DIR/weekly"  -name "\*.sql.gz" -mtime +$(( KEEP\_WEEKLY \* 7 ))  -delete
find "$BACKUP\_DIR/monthly" -name "\*.sql.gz" -mtime +$(( KEEP\_MONTHLY \* 31 )) -delete

log "Backup completed. Disk usage: $(du -sh $BACKUP\_DIR | cut -f1)"

\# Nadaj uprawnienia i dodaj do crona
sudo chmod +x /usr/local/bin/mysql-backup.sh

# Cron: backup codziennie o 2:00 w nocy
crontab -e
# Dodaj:
0 2 \* \* \* /usr/local/bin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1

## Backup na zewnętrzne storage — rclone + S3/Backblaze B2

Backup przechowywany tylko na serwerze głównym nie jest prawdziwym backupem — awaria dysku niszczy i dane, i kopię. Użyj `rclone` do automatycznego uploadu na zewnętrzne storage:

\# Instalacja rclone
curl https://rclone.org/install.sh | sudo bash

# Konfiguracja (interaktywna)
rclone config
# Wybierz: n (nowy remote)
# Nazwa: backblaze-b2
# Typ: b2 (Backblaze B2)
# Podaj: account ID, application key
# Bucket: twoj-bucket-backup

# Test połączenia
rclone lsd backblaze-b2:twoj-bucket-backup

# Upload katalogu backup
rclone sync /backup/mysql backblaze-b2:twoj-bucket-backup/mysql \\
    --transfers 4 \\
    --log-level INFO \\
    --log-file /var/log/rclone-backup.log

\# Dodaj rclone sync do skryptu backup (po rotacji lokalnej)
# W mysql-backup.sh:

log "Uploading to Backblaze B2..."
rclone sync "$BACKUP\_DIR" backblaze-b2:twoj-bucket-backup/mysql \\
    --transfers 4 \\
    --quiet \\
    --log-file "$LOG\_FILE" || alert "rclone upload failed!"

log "Upload complete."

Storage

Cena/GB/mies.

Egress

Uwagi

AWS S3

~$0.023

$0.09/GB

Najdroższy, best-in-class niezawodność, najszersza integracja

Backblaze B2

~$0.006

Darmowy do Cloudflare

Najtańszy, rclone-native, idealny dla backupów

Wasabi

~$0.0068

Darmowy

Min. 90 dni przechowywania per obiekt — uwaga przy częstych nadpisaniach

## Percona XtraBackup — hot backup bez locka

Dla baz danych powyżej kilku GB, gdzie mysqldump trwa zbyt długo, Percona XtraBackup oferuje fizyczne kopie plików InnoDB bez blokowania tabel:

\# Instalacja Percona XtraBackup (Ubuntu 22.04)
wget https://downloads.percona.com/downloads/Percona-XtraBackup-8.0/latest/binary/debian/jammy/x86\_64/percona-xtrabackup-80\_8.0.36-31-1.jammy\_amd64.deb
sudo dpkg -i percona-xtrabackup-80\_\*.deb

# Pełny backup
xtrabackup \\
    --backup \\
    --target-dir=/backup/xtrabackup/full \\
    --user=root \\
    --password=twoje\_haslo

# Incremental backup (tylko zmiany od ostatniego backupu)
xtrabackup \\
    --backup \\
    --incremental-basedir=/backup/xtrabackup/full \\
    --target-dir=/backup/xtrabackup/inc1 \\
    --user=root \\
    --password=twoje\_haslo

# Przygotowanie do przywracania (prepare)
xtrabackup --prepare --target-dir=/backup/xtrabackup/full

# Przywracanie (MySQL musi być zatrzymany!)
sudo systemctl stop mysql
xtrabackup --copy-back --target-dir=/backup/xtrabackup/full
sudo chown -R mysql:mysql /var/lib/mysql
sudo systemctl start mysql

## Testowanie restore — obowiązkowe

Backup bez testu przywracania nie jest wiarygodny. Zautomatyzuj test restore raz w tygodniu:

#!/bin/bash
# /usr/local/bin/test-mysql-restore.sh

BACKUP\_FILE=$(ls -t /backup/mysql/daily/nazwa\_bazy\_\*.sql.gz | head -1)
TEST\_DB="restore\_test\_${RANDOM}"

echo "Testing restore: $BACKUP\_FILE"

# Utwórz testową bazę
mysql -u root -p -e "CREATE DATABASE $TEST\_DB;"

# Przywróć backup
gunzip < "$BACKUP\_FILE" | mysql -u root -p "$TEST\_DB"

# Weryfikuj tabele
TABLE\_COUNT=$(mysql -u root -p -e "SELECT COUNT(\*) FROM information\_schema.tables WHERE table\_schema='$TEST\_DB';" -sN)
echo "Tables restored: $TABLE\_COUNT"

# Usuń bazę testową
mysql -u root -p -e "DROP DATABASE $TEST\_DB;"

echo "Restore test: PASSED ($TABLE\_COUNT tables)"

## Najczęstsze pytania

Dlaczego mysqldump wymaga --single-transaction dla InnoDB? +

Opcja --single-transaction uruchamia zrzut bazy w ramach jednej transakcji REPEATABLE READ. Dzięki temu mysqldump widzi spójny snapshot danych z momentu rozpoczęcia backupu, bez blokowania tabel przez cały czas trwania operacji. Bez tej opcji mysqldump używa LOCK TABLES, co blokuje zapisy do bazy przez cały czas trwania backupu — problematyczne dla produkcyjnych baz z dużym ruchem. Opcja --single-transaction działa TYLKO z silnikiem InnoDB; dla MyISAM nadal potrzebny jest LOCK TABLES.

Jak szybko można przywrócić bazę z mysqldump? +

Czas przywracania zależy od rozmiaru bazy. Dla bazy 1 GB: mysql -u root -p nazwa\_bazy < backup.sql typowo trwa 2-5 minut. Dla baz 10-100 GB może trwać godziny — dlatego dla dużych baz warto rozważyć Percona XtraBackup, który tworzy binarne kopie plików InnoDB i przywraca je znacznie szybciej (minuty zamiast godzin). Przed przywróceniem zawsze testuj backup na oddzielnym serwerze i weryfikuj integralność: mysqlcheck -u root -p --all-databases po przywróceniu.

Jak wybrać między S3, Backblaze B2 a Wasabi do przechowywania backupów? +

AWS S3: najdroższy (~$0.023/GB/mies), ale najbardziej niezawodny z najszerszą integracją. Backblaze B2: najtańszy (~$0.006/GB/mies), darmowy egress do Cloudflare, idealny dla backupów które rzadko pobierasz. Wasabi: ~$0.0068/GB/mies, brak opłat za egress (ale minimum 90 dni przechowywania per obiekt). Dla backupów MySQL rekomendacja: Backblaze B2 za cenę i prostotę, lub Wasabi jeśli backupy są rzadko pobierane ale regularnie nadpisywane.

Czym różni się Percona XtraBackup od mysqldump? +

mysqldump tworzy tekstowy plik SQL z instrukcjami INSERT — przywracanie wymaga ponownego wykonania każdego zapytania, co jest wolne dla dużych baz. Percona XtraBackup kopiuje binarne pliki InnoDB bezpośrednio z dysku (hot backup — bez blokowania), a przywracanie to szybkie kopiowanie plików. XtraBackup obsługuje też incremental backup (tylko zmiany od ostatniego backupu) i backup streaming do S3. Wada: większy plik backupu (brak kompresji SQL), wymagana ta sama lub kompatybilna wersja MySQL/Percona przy przywracaniu.

## Sprawdź oferty pasujące do tego scenariusza

Poniżej masz szybkie przejścia do ofert i stron z kodami rabatowymi tam, gdzie są dostępne.

Contabo

VPS z dużym dyskiem — idealne do lokalnego przechowywania backupów MySQL

VPS

[Aktywuj rabat →](/out/contabo)

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/contabo)

Mikrus

Tani VPS z pełnym dostępem do MySQL i crona — wystarczy do małych projektów

Dev/Test

[Aktywuj rabat →](/out/mikrus)

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/mikrus)

home.pl

Hosting z automatycznymi backupami bazy danych w panelu — bez konfiguracji

Managed

[Aktywuj rabat →](/out/home-pl)

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/home-pl)

## Powiązane strony

-   [MySQL slow query log — optymalizacja zapytań](/baza-wiedzy/mysql-slow-query-log)
-   [MySQL replikacja master-slave](/baza-wiedzy/mysql-replication-master-slave)
-   [Backup — strategia 3-2-1 dla hostingu](/baza-wiedzy/backup-strategia-hosting)
-   [rsync — kopia zapasowa VPS](/baza-wiedzy/rsync-kopia-zapasowa-vps)
-   [Wszystkie artykuły](/baza-wiedzy/)