Резервное копирование базы данных MySQL с помощью снимков ZFS

Я нашел несколько сайтов, посвященных именно этому, но мне не хватает нескольких важных деталей. Общие шаги:

  • Выполнить FLUSH TABLES WITH READ LOCK
  • Сделать снимок ZFS
  • Выполнить РАЗБЛОКИРОВАТЬ ТАБЛИЦЫ

Различные источники сообщают, что InnoDB, который я использую, не фактически соблюдайте FLUSH . В руководстве пользователя MySQL отмечается, что существует вариант FLUSH TABLES ... FOR EXPORT для использования с InnoDB, но это требует указания каждой таблицы отдельно, а не резервного копирования всей базы данных. Я бы предпочел не указывать каждую таблицу в отдельности, потому что есть большая вероятность, что список таблиц не будет синхронизироваться с таблицами, которые действительно существуют.

Другая проблема, с которой я столкнулся, заключается в том, что я планировал сделать что-то вроде mysql -h "$ HOST" -u "$ USERNAME" -p "$ PASSWORD" --execute = "ПРОМЫВАТЬ ТАБЛИЦЫ С БЛОКИРОВКОЙ ЧТЕНИЯ" . Однако это снимает блокировку сразу после выхода из сеанса. Это имеет смысл, но также довольно раздражает, поскольку мне нужно удерживать блокировку чтения, когда я делаю снимок.

Другая моя идея - сделать горячую резервную копию с помощью такого инструмента, как Percona XtraBackup, и сделать снимки резервной копии, но я предпочел бы не платить за запись всех моих данных во второе место только для того, чтобы сделать их снимок.

12
задан 26 September 2016 в 03:46
6 ответов

Если вы используете InnoDB только для всех таблиц и устанавливаете innodb_flush_log_at_trx_commit:

  • 1 (содержимое лог-буфера InnoDB записывается в лог-файл при каждой фиксации транзакции и лог-файл прошивается на диск) или,
  • 2 (содержимое лог-буфера InnoDB записывается в лог-файл после каждой фиксации транзакции и лог-файл прошивается на диск примерно раз в секунду),

тогда вам не нужны FLUSH-таблицы перед тем, как делать снэпшот, просто выполняйте ZFS снэпшот напрямую. InnoDB может восстанавливать данные из журналов фиксации транзакций без потери данных.

Ref: https://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit

4
ответ дан 2 December 2019 в 21:31

Вам нужна полная блокировка базы данных для последовательного резервного копирования (большинства) баз данных.

В руководстве https://dev.mysql.com/doc/refman/5.5/en/backup-methods.html говорится, что FLUSH TABLES WITH READ LOCK правильно для ZFS специально для снимков.

Создание резервных копий с помощью снимка файловой системы

Если вы используете файловую систему Veritas, вы можете сделать резервную копию, например это:

  1. Из клиентской программы выполните FLUSH TABLES WITH READ LOCK .
  2. Из другой оболочки выполните моментальный снимок mount vxfs .
  3. Из первого клиента выполните РАЗБЛОКИРОВАТЬ ТАБЛИЦЫ .
  4. Скопируйте файлы из снимка.
  5. Отключить моментальный снимок.

Подобные возможности создания моментального снимка могут быть доступны в других файловых системах, таких как LVM или ZFS.

Это своего рода смешно , что они упустили тот факт, что вам нужно FLUSH TABLES table_a, table_b, table_c ДЛЯ ЭКСПОРТА для InnoDB из эти инструкции. Также глупо указывать каждую таблицу таким образом. Но, как говорит EEAA, вы можете довольно легко сгенерировать список таблиц, когда начнете резервное копирование.

Что касается удержания блокировки, вы должны поддерживать соединение с базой данных активным при выполнении моментального снимка

Обычно я бы использовал что-то вроде Perl или другой язык программирования, который может подключаться, блокировать базу данных и, поддерживая соединение с базой данных, делать снимок, затем разблокировать и отключиться. Это не сложно. Держу пари, что есть инструменты, которые это уже делают, но написать их легко.

Я говорю «просто, не сложно» и т. Д. Несколько раз. Я предполагаю, что у вас есть базовые навыки программирования или хорошие навыки написания сценариев.

13
ответ дан 2 December 2019 в 21:31

Я скопировал и адаптировал концептуально простой сценарий в Bash, который я нашел в другом сообщении Server Fault от Tobia . Это должно дать вам около 90% пути.

mysql_locked=/var/run/mysql_locked

# flush & lock MySQL, touch mysql_locked, and wait until it is removed
mysql -hhost -uuser -ppassword -NB <<-EOF &
    flush tables with read lock;
    delimiter ;;
    system touch $mysql_locked
    system while test -e $mysql_locked; do sleep 1; done
    exit
EOF

# wait for the preceding command to touch mysql_locked
while ! test -e $mysql_locked; do sleep 1; done

# take a snapshot of the filesystem, while MySQL is being held locked
zfs snapshot zpool/$dataset@$(date +"%Y-%m-%d_%H:%M")

# unlock MySQL
rm -f $mysql_locked

Здесь используемая вами команда mysql запускается в фоновом режиме и касается файла. Он ожидает в фоновом режиме, пока файл исчезнет, ​​прежде чем выйти и, таким образом, разблокировать таблицы. Тем временем основной сценарий ожидает, пока файл существует, затем создает моментальный снимок и удаляет файл.

Файл, на который указывает $ mysql_locked , должен быть доступен для обеих машин, что вы должны иметь возможность достаточно легко, поскольку они оба могут получить доступ к общему набору данных (хотя они могут использовать разные пути, и вы должны это учитывать).

7
ответ дан 2 December 2019 в 21:31

Вам нужно FLUSH TABLES WITH READ LOCK для myisam, потому что это не ведение журнала.

Вам вообще ничего не нужно для innodb, ИМО, потому что это ведение журнала. В любом случае он будет согласованным, просто автоматически откатывает журнал, если что-то происходит в момент, когда вы делаете снимок.

Если вам нужна согласованность на уровне приложения, ваше приложение должно использовать транзакции. Если ваше приложение использует транзакции и innodb, любой моментальный снимок будет согласован и автоматически спросит путь до уровня приложения.

2
ответ дан 2 December 2019 в 21:31

Это мое решение, как создать моментальный снимок ZFS при сохранении блокировки:

mysql << EOF
    FLUSH TABLES WITH READ LOCK;
    system zfs snapshot data/db@snapname
    UNLOCK TABLES;
EOF
1
ответ дан 2 December 2019 в 21:31

Поскольку у нас также были проблемы с FLUSH TABLES WITH READ LOCK для innoDB несколько лет назад, и мы также не хотели чтобы полагаться на способность innoDB восстанавливать несогласованные файлы данных, мы сделали следующее: Используйте второй компьютер с базой данных mariadb/mysql, настроенный как вторичный (ранее известный как «ведомый»). Всякий раз, когда вы хотите сделать снимок zfs, мы просто отключаем mariadb/mysql на вторичном сервере, затем делаем снимок zfs, а затем снова запускаем mariadb/mysql.

Эта установка работает уже около 4 лет с использованием mysqld_multi (для запуска нескольких экземпляров БД на одном компьютере, но на разных портах) без каких-либо сбоев. Более того, мы хотели сразу же использовать моментальные снимки zfs в качестве доступного для записи экземпляра mariaDB/mysql. Поэтому мы немедленно делаем zfs-клон из zfs-snapshot и запускаем mariaDB-Docker Container, используя только что созданный zfs-clone в качестве своего каталога данных. Кроме того, мы используем отдельный BindDNS и маршрутизацию, чтобы сделать mariaDB-Docker-контейнер доступным в нашей внутренней сети с DNS-именем. Таким образом, мы можем получить доступ к db-копиям для чтения/записи из любой точки нашей внутренней офисной сети. (см. https://github.com/ggtools/docker-tools/blob/master/dockerDDNS.py)

Это отличный инструмент для наших разработчиков программного обеспечения: они могут запросить полную копию большой экземпляр mysqsl/mariadb в несколько сотен Гбайт или даже Тбайт за считанные секунды для целей тестирования и разработки.

Все это автоматизировано с помощью нескольких скриптов ruby, которые сами по себе доступны разработчикам в виде Jenkins/Hudson Job. Таким образом, мы даем разработчикам приятный и простой в использовании веб-интерфейс для создания копий БД, когда им это нужно.

0
ответ дан 26 July 2020 в 09:27

Теги

Похожие вопросы