Automatinės DB kopijos: mysqldump, pg_dump, cron

Paleiskite serveryje viena komanda (pirmiausia patikrinkite skripto turinį žemiau):

curl -sSL https://cp.lv/scripts/bekapy-bazy-dannyh.sh | sudo bash

…arba su wget:

wget -qO- https://cp.lv/scripts/bekapy-bazy-dannyh.sh | sudo bash

Skripto turinys bekapy-bazy-dannyh.sh:

#!/usr/bin/env bash
# Creates a MySQL backup script, the first dump and a cron job
set -e

SCRIPT=/opt/scripts/mysql-backup.sh
BACKUP_DIR=/var/backups/mysql

# 1. Directories for the script and the dumps
sudo mkdir -p /opt/scripts "$BACKUP_DIR"

# 2. Create the backup script itself (quoted 'EOF': variables expand at run time)
sudo tee "$SCRIPT" > /dev/null << 'EOF'
#!/bin/bash
set -euo pipefail
DB_NAME="app_db"
DB_USER="backup_user"
BACKUP_DIR="/var/backups/mysql"
KEEP_DAYS=7
DATE=$(date +%F_%H-%M)
mkdir -p "$BACKUP_DIR"
mysqldump --single-transaction --quick --user="$DB_USER" \
  "$DB_NAME" | gzip > "$BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz"
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$KEEP_DAYS -delete
EOF
sudo chmod +x "$SCRIPT"

# 3. Take the first backup right away
sudo "$SCRIPT"

# 4. Cron job: every day at 03:30
echo "30 3 * * * root $SCRIPT >> /var/log/db-backup.log 2>&1" | sudo tee /etc/cron.d/db-backup > /dev/null

echo "Done: script $SCRIPT created, first dump in $BACKUP_DIR, cron configured."

Duomenų bazės atsarginė kopija yra tai, kas išgelbsti projektą įvykus disko gedimui, klaidingai įvykdžius DROP TABLE arba nepavykus migracijai. Joks talpinimas nepanaikina jūsų pačių atsakomybės už kopijas: laikykite jas ir tikrinkite atkūrimą. Žemiau — veikiantys scenarijai MySQL/MariaDB ir PostgreSQL su automatiniu paleidimu per cron.

Patikimos kopijos principas

  • Reguliarumas — pagal tvarkaraštį, be rankinio įsikišimo.
  • Rotacija — laikyti N naujausių kopijų, senas šalinti.
  • Išorinė saugykla — kopijuoti dump failus į kitą serverį ar objektinę saugyklą, o ne tik į tą patį diską.
  • Atkūrimo patikra — periodiškai atstatyti kopiją į testinę duomenų bazę.

MySQL/MariaDB kopija

Įrankis mysqldump sukuria loginę kopiją — SQL failą su visais duomenimis. Sukurkite failą /opt/scripts/mysql-backup.sh redaktoriuje (nano, vim arba mcedit):

sudo mkdir -p /opt/scripts
sudo nano /opt/scripts/mysql-backup.sh

Scenarijaus turinys:

#!/bin/bash
set -euo pipefail

DB_NAME="app_db"
DB_USER="backup_user"
BACKUP_DIR="/var/backups/mysql"
KEEP_DAYS=7
DATE=$(date +%F_%H-%M)

mkdir -p "$BACKUP_DIR"

mysqldump --single-transaction --quick --user="$DB_USER" \
  "$DB_NAME" | gzip > "$BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz"

# pašalinti kopijas, senesnes nei KEEP_DAYS dienų
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$KEEP_DAYS -delete

Arba sukurkite visą scenarijų viena komanda — nukopijuokite ir įklijuokite į konsolę (kabutės 'EOF' svarbios: $ kintamieji turi likti scenarijuje, o ne išsiplėsti dabar):

sudo tee /opt/scripts/mysql-backup.sh > /dev/null << 'EOF'
#!/bin/bash
set -euo pipefail

DB_NAME="app_db"
DB_USER="backup_user"
BACKUP_DIR="/var/backups/mysql"
KEEP_DAYS=7
DATE=$(date +%F_%H-%M)

mkdir -p "$BACKUP_DIR"

mysqldump --single-transaction --quick --user="$DB_USER" \
  "$DB_NAME" | gzip > "$BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz"

find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$KEEP_DAYS -delete
EOF
sudo chmod +x /opt/scripts/mysql-backup.sh

Vėliavėlė --single-transaction nuima nuoseklią momentinę kopiją neužrakinant lentelių (InnoDB atveju). Kad slaptažodis nebūtų saugomas scenarijuje, sukurkite failą ~/.my.cnf su teisėmis 600. Atidarykite jį redaktoriuje:

nano ~/.my.cnf

Failo turinys:

[client]
user=backup_user
password=StrongPassword123!

Arba sukurkite failą viena komanda — nukopijuokite ir įklijuokite į konsolę:

tee ~/.my.cnf > /dev/null << 'EOF'
[client]
user=backup_user
password=StrongPassword123!
EOF
chmod 600 ~/.my.cnf

Padarykite scenarijų vykdomą:

chmod +x /opt/scripts/mysql-backup.sh

PostgreSQL kopija

Analogiškas scenarijus su pg_dump (custom formatas patogesnis daliniam atkūrimui). Sukurkite failą /opt/scripts/postgres-backup.sh redaktoriuje:

sudo nano /opt/scripts/postgres-backup.sh

Scenarijaus turinys:

#!/bin/bash
set -euo pipefail

DB_NAME="app_db"
BACKUP_DIR="/var/backups/postgres"
KEEP_DAYS=7
DATE=$(date +%F_%H-%M)

mkdir -p "$BACKUP_DIR"

pg_dump -Fc "$DB_NAME" > "$BACKUP_DIR/${DB_NAME}_${DATE}.dump"
find "$BACKUP_DIR" -name "*.dump" -mtime +$KEEP_DAYS -delete

Arba sukurkite visą scenarijų viena komanda (kabutės 'EOF' išsaugo $ kintamuosius scenarijaus viduje):

sudo tee /opt/scripts/postgres-backup.sh > /dev/null << 'EOF'
#!/bin/bash
set -euo pipefail

DB_NAME="app_db"
BACKUP_DIR="/var/backups/postgres"
KEEP_DAYS=7
DATE=$(date +%F_%H-%M)

mkdir -p "$BACKUP_DIR"

pg_dump -Fc "$DB_NAME" > "$BACKUP_DIR/${DB_NAME}_${DATE}.dump"
find "$BACKUP_DIR" -name "*.dump" -mtime +$KEEP_DAYS -delete
EOF
sudo chmod +x /opt/scripts/postgres-backup.sh

PostgreSQL slaptažodis laikomas faile ~/.pgpass (teisės 600). Atidarykite jį redaktoriuje:

nano ~/.pgpass

Failo turinys (formatas host:port:db:user:password):

localhost:5432:app_db:backup_user:StrongPassword123!

Arba sukurkite failą viena komanda:

tee ~/.pgpass > /dev/null << 'EOF'
localhost:5432:app_db:backup_user:StrongPassword123!
EOF
chmod 600 ~/.pgpass

Tvarkaraštis cron sistemoje

Atidarykite vartotojo, kurio vardu veikia scenarijai, crontab:

crontab -e

Pridėkite užduotis — kasdienė kopija 3:30 nakties:

30 3 * * * /opt/scripts/mysql-backup.sh >> /var/log/db-backup.log 2>&1
30 3 * * * /opt/scripts/postgres-backup.sh >> /var/log/db-backup.log 2>&1

Patikrinkite, ar užduotis įrašyta: crontab -l.

Kopijavimas į kitą serverį

Scenarijaus gale pridėkite kopijos siuntimą į nuotolinį hostą per SSH:

rsync -az "$BACKUP_DIR"/ [email protected]:/remote/db-backups/

Atkūrimas iš kopijos

MySQL:

gunzip < app_db_2026-04-17_03-30.sql.gz | mysql -u root -p app_db

PostgreSQL (custom formatas):

pg_restore -d app_db --clean app_db_2026-04-17_03-30.dump

Dažni klausimai

Kaip dažnai daryti kopijas? Priklauso nuo to, kiek duomenų esate pasiruošę prarasti. Aktyviai svetainei — kasdien, kritiniams duomenims — kelis kartus per dieną arba naudojant nepertraukiamą WAL archyvavimą (PostgreSQL).

Ar mysqldump užrakina bazę darbo metu? Su vėliavėle --single-transaction InnoDB lentelėms užrakinimo nėra — nuimama nuosekli momentinė kopija. MyISAM atveju užrakinimas galimas.

Kur laikyti dump failus? Ne tik tame pačiame diske. Kopijuokite į atskirą serverį arba objektinę saugyklą: disko gedimas neturi nusinešti ir bazės, ir jos atsarginių kopijų.

Kaip įsitikinti, kad kopija veikianti? Periodiškai atstatykite ją į atskirą testinę duomenų bazę ir patikrinkite duomenis. Nepatikrinta kopija atsargine kopija laikyti negalima.

Atsarginės kopijos yra jūsų atsakomybės sritis, ir rekomenduojame jas turėti visada. Duomenų bazę su automatinėmis kopijomis galite talpinti planuose VPS serverio nuoma arba specializuotame VPS duomenų bazėms.

Inga Vītola