Міграція бази даних сайту
Міграція БД — технічно найрискованіший етап будь-якої інфраструктурної роботи. Втрата даних або недоступність сайту під час міграції мають прямі фінансові наслідки. Підхід залежить від розміру БД, допустимого downtime та вимог до узгодженості даних.
Стратегії за downtime
Maintenance window (найпростіший): сайт у режимі обслуговування → дамп → перенос → запуск. Downtime = час дампу + переносу. Прийнятно для БД до 10 GB у ночі.
Online migration: репліка з source на target, мінімальний downtime тільки для переключення. Для MySQL — Percona XtraBackup або binlog replication. Для PostgreSQL — pglogical або pg_basebackup + WAL shipping.
Blue-Green: паралельна БД, застосунок пише в обидві, потім перемикання. Складніше, але нульовий downtime.
MySQL: безпечний дамп та відновлення
# Дамп з блокуванням для консистентності
mysqldump \
--single-transaction \
--routines \
--triggers \
--events \
--hex-blob \
--default-character-set=utf8mb4 \
-u root -p mysite_db \
| gzip > /backup/mysite_$(date +%Y%m%d_%H%M%S).sql.gz
# Розмір до стиснення (для оцінки часу)
mysql -u root -p -e "
SELECT
table_schema AS 'Database',
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
FROM information_schema.tables
WHERE table_schema = 'mysite_db'
GROUP BY table_schema;
"
# Відновлення
gunzip < /backup/mysite_20241201_030000.sql.gz | mysql -u root -p new_db
PostgreSQL: pg_dump та pg_restore
# Користувацький формат (швидше, стиснений, паралельне відновлення)
pg_dump \
-U postgres \
-d mysite_db \
-F custom \
-f /backup/mysite_$(date +%Y%m%d).dump \
--verbose
# Паралельне відновлення
pg_restore \
-U postgres \
-d new_db \
-j 4 \ # 4 паралельних потоки
--verbose \
/backup/mysite_20241201.dump
# Перевірка цілісності
psql -U postgres -d new_db -c "SELECT COUNT(*) FROM users;"
psql -U postgres -d new_db -c "SELECT COUNT(*) FROM posts;"
Online міграція PostgreSQL з мінімальним downtime
# 1. Налаштовуємо репліку через pglogical
# На source
psql -c "CREATE EXTENSION pglogical;"
psql -c "SELECT pglogical.create_node(node_name := 'provider', dsn := 'host=source dbname=mysite user=replication');"
psql -c "SELECT pglogical.create_replication_set('all_tables');"
psql -c "SELECT pglogical.replication_set_add_all_tables('all_tables', ARRAY['public']);"
# На target
psql -c "CREATE EXTENSION pglogical;"
psql -c "SELECT pglogical.create_node(node_name := 'subscriber', dsn := 'host=target dbname=mysite_new user=replication');"
psql -c "SELECT pglogical.create_subscription(
subscription_name := 'sub_mysite',
provider_dsn := 'host=source dbname=mysite user=replication password=secret'
);"
# 2. Чекаємо синхронізації
psql -c "SELECT * FROM pglogical.show_subscription_status();"
# 3. Downtime: зупиняємо запис, перемикаємо застосунок на нову БД
# Downtime = секунди, не години
Валідація після міграції
# Порівнюємо кількість рядків у критичних таблицях
for table in users posts orders products; do
src=$(mysql -h source -u root -p -se "SELECT COUNT(*) FROM mysite.$table")
dst=$(mysql -h target -u root -p -se "SELECT COUNT(*) FROM mysite.$table")
if [ "$src" != "$dst" ]; then
echo "MISMATCH: $table: $src vs $dst"
else
echo "OK: $table: $src rows"
fi
done
Розміри БД та приблизний час
| Розмір БД | Дамп + перенос | pg_restore (паралельно) |
|---|---|---|
| до 1 GB | 2–10 хв | 1–5 хв |
| 1–10 GB | 10–60 хв | 5–20 хв |
| 10–100 GB | 1–8 годин | 30 хв – 3 години |
| 100 GB+ | Online migration | — |
Повна міграція з плануванням, тестовим прогоном та rollback-планом — 1–5 днів залежно від складності.







