Налаштування MySQL Multi‐Source Replication за допомогою GTID

💡 Усі статті, обговорення, новини про DevOps — в одному місці. Приєднуйтесь до DevOps спільноти!

Привіт усім! Мене звати Ігор Стецюк, я DevOps-інженер в компанії Futurra Group. Ми працюємо у сфері EdTech, зокрема розробляємо та просуваємо сервіс MathMaster — застосунок, що надає математичні консультації 24/7.

У цій статті я хочу поділитися технічним рішенням, що значно полегшило робочий флоу та дозволило забезпечити надійність та доступність наших даних, а саме — налаштування MySQL Multi-Source Replication на ZFS-файловій системі. Цю схему ми використовуємо для потреб команди аналітиків та розробників, коли потрібно перевірити поведінку коду в робочому середовищі на живих даних, а також для створення резервних копій, що є критично важливим для продукту, адже ми робимо знімки всіх баз даних щогодини.

У чому була проблема

У міру розвитку продукту в нашій роботі з MySQL-базами даних в хмарі DigitalOcean накопичувалася низка питань, що потребували вирішення.

По-перше, був запит від команди аналітиків — треба прискорити важкі вибірки, а також хотілось отримувати всі необхідні дані з єдиного місця.

По-друге, треба було пришвидшити процес створення резервних копій з read-only серверів, та й хотілося робити їх частіше. Для вирішення цих задач спробували вертикально масштабувати read-only сервер, проте це все ще не покривало всіх наших потреб, адже, наприклад, той же mysqldump постійно перекачує базу, а єдиного місця з усіма БД усе ще не було.

І, звісно, бажання одразу протестувати все на проді без шкоди реальним даним завжди було і буде актуальним.

Тож я запропонував ідею поєднання Multi-Source та ZFS і швидко перейшов до реалізації цієї схеми. Далі детально та покроково розповідаю, як саме я діяв.

Для початку трошки теорії

Спочатку розглянемо, як працює механізм реплікації, а також інструменти та поняття, які будуть застосовані в процесі.

MySQL Multi-Source Replication — це механізм, який дозволяє реплікувати дані з кількох джерел у єдину БД. Це особливо корисно у випадку, коли є декілька баз, які містять пов’язані дані і ви хочете мати єдину точку доступу до них. Саме за допомогою Multi-Source Replication ви можете сконфігурувати таку точку та забезпечити автоматичну реплікацію даних між джерелами.

GTID (Global Transaction Identifier) в MySQL — це унікальний ідентифікатор для транзакцій у реплікаційній топології. Використовуючи GTID, ви можете однозначно ідентифікувати кожну транзакцію в БД, незалежно від того, на якому сервері вона відбулася.

GTID складається з двох основних частин:

  1. UUID — унікальний ідентифікатор для кожного сервера БД у реплікаційній топології.
  2. Sequence Number — порядковий номер транзакції, який відображається на конкретному сервері. Кожен сервер зберігає цей локальний лічильник для відстеження номерів транзакцій, які відбулися на цьому сервері.

ZFS файлова система дає можливість дешево створювати знімки файлової системи, використовуючи ZFS Snapshot, а також відновлювати стан файлової системи та видаляти застарілі знімки.

Розглянувши основні концепти, пов’язані з налаштуванням Multi-Source Replication на ZFS-файловій системі, перейдемо до конкретних прикладів, щоб відстежити, як можна використовувати цей механізм реплікації для убезпечення даних.

Схема інфраструктури

Так історично склалося, що наші кластери баз даних перебувають в DigitalOcean. Цей провайдер дає можливість легко створювати та налаштовувати інфраструктуру, має зручний API та детальну документацію.

Крім того, ми обрали саме цього провайдера, адже він має Terraform провайдер, який активно розвивається та підтримується в належному стані. Також DigitalOcean має досить привабливу цінову політику, що дозволяє зменшити витрати на утримання інфраструктури.

Ми маємо дві БД як сервіс DigitalOcean, окремий сервер з базою даних та сам сервер реплікації.

DB1 — DBaaS (digitalocean)
DB2 — DBaaS (digitalocean)
DB3 — self-hosted (Percona MySQL Server 8.0)
mysql-slave — self-hosted (Percona MySQL Server 8.0). Розгорнуто на dedicated server.

На схемі зображено два незалежних один від одного кластери БД mysql з master (RW) ⇒ slave (RO) реплікаціями, окрема БД (DB3), що перебуває у віртуальній машині, та Multi-Source Replication node — сервер, який буде реплікувати всі наші кластери.

Практика

Налаштовуємо Multi-Source Replication node

OS Ubuntu 22.04.3 LTS

Для ZFS нам потрібен окремий диск. У прикладі я використав /dev/sda. Для встановлення та підготовки ZFS зробимо такі кроки:

echo "deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs) main universe" |
tee  /etc/apt/sources.list.d/zfs.list
apt update && apt install -y zfsutils-linux
zpool create -m none zp_mysql /dev/sda
zfs set compression=lz4 atime=off logbias=throughput zp_mysql
zfs create -o recordsize=128K -o atime=off -o compression=lz4 zp_mysql/mysql
zfs create -o mountpoint=/mysql_data/log -o recordsize=128K -o atime=off -o compression=lz4 zp_mysql/mysql/log
zfs create -o mountpoint=/mysql_data/data -o recordsize=16k -o primarycache=metadata -o atime=off -o compression=off zp_mysql/mysql/data

Переносимо MySQL до нового сховища

Спочатку змінимо datadir налаштування в [mysqld]-секції конфігураційного файлу mysql:

[mysqld]
datadir                    = /mysql_data/data/

Внесемо інші налаштування до mysql та запустимо сервіс:

[mysqld]
# logs
log_bin                     = /mysql_data/log/binlog
relay_log                   = /mysql_data/log/relaylog
relay_log_index             = /mysql_data/log/relaylog.index
binlog_expire_logs_seconds  = 604800
max_binlog_size             = 100M
relay_log_recovery          = on
master_info_repository      = 'TABLE'
relay_log_info_repository   = 'TABLE'

# GTID Based Replication Parameter
server-id=19
gtid_mode=ON
enforce-gtid-consistency=1
log_slave_updates=1
read-only=1
super_read_only=1

# For ZFS
innodb_doublewrite = 0 # ZFS is transactional
innodb_use_native_aio = 0
innodb_flush_method = fsync
innodb_read_io_threads = 10
innodb_write_io_threads = 10

read-only=1 та super_read_only=1 — ці параметри необхідно ввімкнути, щоб захистити дані від внесення змін, навіть тим користувачам, що мають адміністративні права.

Переносимо дані mysql до нового сховища:

systemctl stop mysql
rsync -auxHAXSv --chown=mysql:mysql /var/lib/mysql/* /mysql_data/data/
systemctl start mysql

Налаштовуємо DB-3 node

OS Ubuntu 22.04.3 LTS

Додамо такі налаштування в конфігурацію сервера:

[mysqld]
bind-address=0.0.0.0
log_bin=/var/lib/mysql/binlog

# GTID Based Replication Parameter
server-id=3
gtid_mode=ON
enforce-gtid-consistency=1

server-id=3 — цей параметр встановлює ідентифікатор сервера для реплікації. Кожен сервер повинен мати унікальний ідентифікатор в системі реплікації.

gtid_mode=ON — цей параметр вмикає режим GTID (Global Transaction Identifier) для реплікації. GTID дозволяє ідентифікувати та відстежувати транзакції в реплікаційному процесі.

enforce-gtid-consistency=1 — цей параметр вимагає, щоб транзакції на репліках були відповідно синхронізовані з джерелом за допомогою GTID. Він забезпечує консистентність даних у реплікаційному середовищі.

Змінну enforce-gtid-consistency слід встановлювати на ON у всіх середовищах реплікації MySQL, де важлива стійкість даних. Це запобігатиме виконанню операцій, які можуть пошкодити дані на реплікованому сервері.

Підготуємо DigitalOcean кластери для реплікації

Отримуємо ідентифікатори (ID) наших кластерів

export DIGITALOCEAN_TOKEN="dop_v1_1d05faa83e157d93ddbe2d7a0b7e4c9497679dce5745761995d70d641b387f2a"

curl -sX GET \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
  "https://api.digitalocean.com/v2/databases" |
  jq --sort-keys '.databases[]|{id, name, region, status}'

# Output

{
  "id": "29ad047f-9691-4ba3-96f4-4653a2c6400c",
  "name": "db-1",
  "region": "fra1",
  "status": "online"
}

{
  "id": "8689da6d-b09c-4423-b4da-1d38498dabc8",
  "name": "db-2",
  "region": "fra1",
  "status": "online"
}

Нам необхідно змінити binlog_retention_period:

curl -sX PATCH \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
  -d '{"config": {"binlog_retention_period": 86400}}' \
 "https://api.digitalocean.com/v2/databases/29ad047f-9691-4ba3-96f4-4653a2c6400c/config"

curl -sX PATCH \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
  -d '{"config": {"binlog_retention_period": 86400}}' \
"https://api.digitalocean.com/v2/databases/8689da6d-b09c-4423-b4da-1d38498dabc8/config"

Перевіримо зміни:

curl -sX GET \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
"https://api.digitalocean.com/v2/databases/29ad047f-9691-4ba3-96f4-4653a2c6400c/config" |
jq '.config.binlog_retention_period'

curl -sX GET \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
"https://api.digitalocean.com/v2/databases/8689da6d-b09c-4423-b4da-1d38498dabc8/config" |
jq '.config.binlog_retention_period'

Саме час налаштувати реплікацію

Підмикаємося до наших кластерів (вихідні сервери) та створюємо обліковий запис для реплікації:

#DB-RW-1 node
CREATE USER 'replication_user'@'64.225.109.74' 
 IDENTIFIED WITH mysql_native_password 
 BY '1DPpYPOKYi4DLPskGdYh';
GRANT REPLICATION SLAVE ON *.* 
 TO 'replication_user'@'64.225.109.74';
FLUSH PRIVILEGES;

#DB-RW-2 node
CREATE USER 'replication_user'@'64.225.109.74'
 IDENTIFIED WITH mysql_native_password
 BY 'ILce3w929XGNA1ayURRa';
GRANT REPLICATION SLAVE ON *.* 
 TO 'replication_user'@'64.225.109.74';
FLUSH PRIVILEGES;

#DB-3 node
CREATE USER 'replication_user'@'64.225.109.74'
 IDENTIFIED WITH mysql_native_password
 BY '6yKHQtoqewzxek8HTkul';
GRANT REPLICATION SLAVE ON *.* 
 TO 'replication_user'@'64.225.109.74';
FLUSH PRIVILEGES;

Нам необхідно налаштувати реплікацію з наступних баз:

  • parrot та fish з серверу DB-1;
  • dogs з серверу DB-2;
  • cats з серверу DB-3.

Робимо mysqldump баз, щоб не навантажувати головний сервер; backup можна виконувати з будь-якої ноди кластеру для читання.

# DB-1-RO-1
mysqldump --single-transaction \
        --quick \
        --add-drop-database \
        --add-drop-table \
        --triggers \
        --routines \
        --events \
        --source-data \
        --databases parrots fish > db-1.sql

# DB-2-RO-2
mysqldump --single-transaction \
        --quick \
        --add-drop-database \
        --add-drop-table \
        --triggers \
        --routines \
        --events \
        --source-data \
        --databases dogs > db-2.sql

# DB-3
mysqldump --single-transaction \
        --quick \
        --add-drop-database \
        --add-drop-table \
        --triggers \
        --routines \
        --events \
        --source-data \
        --databases cats > db-3.sql

--single-transaction — цей параметр забезпечує виконання резервного копіювання в одній транзакції, що дозволяє уникнути блокування таблиць на час створення резервної копії;

--quick — дозволяє використовувати швидший метод для вибірки даних, що може бути корисним для великих таблиць;

--add-drop-database — параметр, що додає до SQL-файлу команди для видалення БД перед її створенням;

--add-drop-table — цей параметр додає до SQL-файлу команди для видалення таблиць перед їхнім створенням, допомагаючи уникнути конфліктів під час відновлення резервної копії;

--triggers — параметр, що додає в резервну копію тригери, які визначені в БД;

--routines — цей параметр додає в резервну копію збережені процедури та функції, які визначені в БД;

--events — параметр, що додає в резервну копію заплановані події (events), які визначені в БД;

--source-data — цей параметр додає в резервну копію дані з таблиць;

--databases — тут вказані назви баз даних, які потрібно додати в резервну копію.

Далі нам необхідно отримати GTID-значення з кожного файлу резервної копії. Зберігаємо їх та видаляємо з дамп-файлу ці рядки. Якщо ж дамп дуже великий, можна виконати RESET MASTER після кожного відновлення з дампу. Якщо цього не зробити, ми отримаємо помилку:

ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the added gtid set must not overlap with @@GLOBAL.GTID_EXECUTED

Отримуємо GLOBAL.GTID_PURGED

head -n 50 db-1.sql | less -N
# Output
  db-1 34 SET @@GLOBAL.GTID_PURGED=/*!80000 '+'*/ '4d7dbef6-3777-11ee-807c-0ae964d12771:1-33';

head -n 50 db-2.sql | less -N
# Output
  db-2 34 SET @@GLOBAL.GTID_PURGED=/*!80000 '+'*/ '9784567e-3777-11ee-bc2e-ea23c8e356f2:1-30';

head -n 50 db-3.sql | less -N
# Output
  db-3 34 SET @@GLOBAL.GTID_PURGED=/*!80000 '+'*/ '0289f920-376d-11ee-a2ef-363cbae02daa:1-27';

Видаляємо ці рядки з файлів резервної копії, у нашому випадку це рядок 34.

sed -i 34'{/./d;}' db-1.sql
sed -i 34'{/./d;}' db-2.sql
sed -i 34'{/./d;}' db-3.sql

Якщо потрібно видалити декілька рядків, вказуємо початковий номер рядку та кінцевий через кому: sed -i 34,44'{/./d;}' db-1.sql

Ці три рядки GLOBAL.GTID_PURGED об’єднуємо в одну команду та виконуємо її у випадку, якщо ми вирізали 34-й рядок з кожного дампу або після завантаження всіх дампів. Якщо щось пішло не так і вам потрібно записати нові значення, виконайте RESET MASTER.

SET @@GLOBAL.GTID_PURGED=/*!80000 '+'*/ '4d7dbef6-3777-11ee-807c-0ae964d12771:1-33,9784567e-3777-11ee-bc2e-ea23c8e356f2:1-30,0289f920-376d-11ee-a2ef-363cbae02daa:1-27';

Усі наші дампи завантажуємо в mysql:

mysql < db-1.sql
mysql < db-2.sql
mysql < db-3.sql

Та нарешті створюємо репліки на сервері multi-slave:

CHANGE REPLICATION SOURCE TO
    SOURCE_HOST='db-1-do-user-9604885-0.b.db.ondigitalocean.com',
    SOURCE_PORT= 25060,
    SOURCE_USER='replication_user',
    SOURCE_PASSWORD='1DPpYPOKYi4DLPskGdYh',
    SOURCE_AUTO_POSITION=1
    FOR CHANNEL 'db-1';

CHANGE REPLICATION SOURCE TO
    SOURCE_HOST='db-2-do-user-9604885-0.b.db.ondigitalocean.com',
    SOURCE_PORT= 25060,
    SOURCE_USER='replication_user',
    SOURCE_PASSWORD='ILce3w929XGNA1ayURRa',
    SOURCE_AUTO_POSITION=1
    FOR CHANNEL 'db-2';

CHANGE REPLICATION SOURCE TO
    SOURCE_HOST='157.230.97.56',
    SOURCE_PORT= 3306,
    SOURCE_USER='replication_user',
    SOURCE_PASSWORD='6yKHQtoqewzxek8HTkul',
    SOURCE_AUTO_POSITION=1
    FOR CHANNEL 'db-3';

Запускаємо слейв та перевіряємо статус:

mysql> START SLAVE;
Query OK, 0 rows affected, 1 warning (0.13 sec)

mysql> SELECT CHANNEL_NAME,SERVICE_STATE,LAST_ERROR_NUMBER,LAST_ERROR_MESSAGE
    -> FROM performance_schema.replication_connection_status;
+--------------+---------------+-------------------+--------------------+
| CHANNEL_NAME | SERVICE_STATE | LAST_ERROR_NUMBER | LAST_ERROR_MESSAGE |
+--------------+---------------+-------------------+--------------------+
| db-1         | ON            |                 0 |                    |
| db-2         | ON            |                 0 |                    |
| db-3         | ON            |                 0 |                    |
+--------------+---------------+-------------------+--------------------+
3 rows in set (0.00 sec)

Як бачимо, все добре. Детальніше статус реплік можна подивитись командою SHOW SLAVE STATUS FOR CHANNEL ’db-2’\G

ZFS snapshots & rollback

ZFS Snapshot (знімок) — це віртуальна копія файлової системи або об’єктного сховища на конкретний момент часу. Основна ідея полягає в тому, що знімки зберігають лише зміни між початковим станом файлової системи та поточним знімком, що дозволяє ефективно використовувати простір на диску. Знімки використовуються для резервного копіювання, відновлення даних, створення тестових середовищ та багатьох інших завдань.

Коли ви робите знімок в ZFS, він зберігає інформацію про стан об’єктів у файловій системі на момент створення. Знімки не вимагають створення фактичних копій даних, тому вони генеруються майже миттєво та займають мінімальний об’єм місця.

ZFS Rollback (відновлення) — це операція відновлення файлової системи до стану, що був на момент створення знімку.

Під час виконання rollback ZFS забезпечує консистентність даних: це означає, що дані повертаються до попереднього стану без ризику втрати або пошкодження. Ця операція є миттєвою, навіть на великих об’ємних накопичувачах.

Важливо зауважити, що знімки та rollback у ZFS — це операції, доступні на рівні файлової системи і вони працюють незалежно від операційки. Це робить їх потужними інструментами для керування даними та забезпечення надійності та доступності інформації.

Для створення знімків я використовую скрипт, який запускається в кроні погодинно та виконує ротацію застарілих знімків. Переглянути можна за посиланням: zfs_snapshot_rotate.sh

Нижче наведено приклад знімків з реального сервера:

chip@mysql-slave:~$ zfs list -t snapshot

NAME                                      USED  AVAIL     REFER  MOUNTPOINT
zp_mysql/mysql/data@2023-08-28_10-00-01   417M      -      110G  -
zp_mysql/mysql/data@2023-08-28_11-00-01   190M      -      110G  -
zp_mysql/mysql/data@2023-08-28_12-00-01   199M      -      110G  -
zp_mysql/mysql/data@2023-08-28_13-00-01   212M      -      110G  -
zp_mysql/mysql/data@2023-08-28_14-00-01   233M      -      110G  -
zp_mysql/mysql/data@2023-08-28_15-00-01   244M      -      110G  -
zp_mysql/mysql/data@2023-08-28_16-00-01   250M      -      110G  -
zp_mysql/mysql/data@2023-08-28_17-00-01   258M      -      110G  -
zp_mysql/mysql/data@2023-08-28_18-00-01   260M      -      110G  -
zp_mysql/mysql/data@2023-08-28_19-00-01   247M      -      110G  -
zp_mysql/mysql/data@2023-08-28_20-00-02   251M      -      110G  -
zp_mysql/mysql/data@2023-08-28_21-00-01   270M      -      110G  -
zp_mysql/mysql/data@2023-08-28_22-00-01   293M      -      111G  -
zp_mysql/mysql/data@2023-08-28_23-00-01   301M      -      111G  -
zp_mysql/mysql/data@2023-08-29_00-00-01   314M      -      111G  -
zp_mysql/mysql/data@2023-08-29_01-00-01   315M      -      111G  -
zp_mysql/mysql/data@2023-08-29_02-00-01   307M      -      111G  -
zp_mysql/mysql/data@2023-08-29_03-00-01   281M      -      111G  -
zp_mysql/mysql/data@2023-08-29_04-00-01   271M      -      111G  -
zp_mysql/mysql/data@2023-08-29_05-00-01   282M      -      111G  -
zp_mysql/mysql/data@2023-08-29_06-00-01   238M      -      111G  -
zp_mysql/mysql/data@2023-08-29_07-00-01   219M      -      111G  -
zp_mysql/mysql/data@2023-08-29_08-00-01   195M      -      111G  -
zp_mysql/mysql/data@2023-08-29_09-00-01   177M      -      111G  -

Для того, щоб відкотитися до останньої копії, вам необхідно виконати команду zfs rollback <name>. У нашому випадку це zfs rollback zp_mysql/mysql/data@2023-08-29_08-00-01.

Проте якщо ви плануєте повернутися до історичної попередньої копії, необхідно видалити всі копії, що йдуть за нею. Це можна зробити автоматично, виконавши команду з ключем -r: zfs rollback -r zp_mysql/mysql/data@2023-08-29_06-00-01.

Якщо ви перевірите стан ваших знімків, то побачите, що копій zp_mysql/mysql/data@2023-08-29_08-00-01 та zp_mysql/mysql/data@2023-08-29_07-00-01 уже не існує.

Також ми можемо, наприклад, відправити знімки на інший сервер та розгорнути необхідну нам копію БД. Можна також створити архів знімку та використовувати його для різних пісочниць розробників. Усі ці маніпуляції виконуються набагато швидше, ніж у випадку використання mysqldump.

Висновок

Очевидно, що знімки та rollbacks у ZFS є потужними інструментами для керування даними та забезпечення надійності й доступності інформації. Знімки використовуються для резервного копіювання, відновлення даних, створення тестових середовищ та багатьох інших завдань. Rollback дозволяє скасувати всі зміни, які були зроблені після створення знімку і повернутися до попереднього стану.

За допомогою MySQL Multi-Source Replication можна налаштувати реплікацію з декількох серверів на один. Зокрема, ми розглянули налаштування реплікації з трьох серверів, а також процес налаштування знімків та rollbacks в ZFS. Описану в статті схему зручно використовувати для створення резервних копій, аналітики, «тестанути, як воно буде на проді» і водночас не завдати шкоди продакшн-даним.

Використовуючи ці інструменти, можна забезпечити надійність та доступність даних, що є критично важливим для бізнесу.

👍ПодобаєтьсяСподобалось11
До обраногоВ обраному7
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

а можете пікдазати алгортм відновлення даних mysql з бекапу на ноді з ZFS в випадку відмови диску на якому лежить zfs ? Безвідносно до реплікації, просто хочу зрозуміти порядок дій backup/restore. Додаємо новий диск, додаєм zfs pool, а далі ?

Для цього Вам необхідно десь зберігати копії снепшотів, наприклад в архівах на s3, і обов"язково у вас повинен бути один рекурсивний снепшот, поверх нього можете додавати diff снепшоти. Потім зможете відновитись з цих архівів.
docs.oracle.com/...​er-2.html#gentextid-11564

Чому вибрали DBaaS DigitalOcean? Так, я бачив в тексті, що то склалося історично. Але з технічної та економічної точки зору, не порівнювали з OCI (MDS)?

Я б ще порекомендував відфільтрувати базу mysql, бо вона одна і та ж на всіх трьох вихідних серверах БД. Або ж навпаки додати фільтр лише на бази, що потрібно реплікувати
ПС: також додам, що Oracle відходить від понять «master» та «slave» і радить використовувати source та replica.

Для створення знімків я використовую скрипт, який запускається в кроні погодинно та виконує ротацію застарілих знімків.

У тій же убунті в штатному репозиторії є zfs-auto-snapshot, і здається ще кілька пакетів аналогічної функціональності, писати власний немає потреби.

Якщо вже користуватись ZFS, чи не простіше було б на її ж рівні і реплікацію робити, з zfs send/receive? Тим більше, якщо все одно снапшотити «на гарячу» живу базу, не знаю наскільки це безпечно.

zfs-auto-snapshot

— гарна альтернатива. Реплікацію на рівні zfs ніяк не зробити, бо нема доступу до сорс серверу бази даних, це database as service.

>>

а чому ви не робите snapshot файлової з binlog?

бо це database as service в digitalocean.
За

clone плагін

дякую, наступного разу спробую. Ви праві, на час снепшоту бажано підготувати базу для цієї процедури, додам цю опцію в скрипт. Але і в даному прикладі схема працює надійно та поки проблем з нею не було.

Підписатись на коментарі