Резервне копіювання бази даних MySQL за допомогою знімків ZFS


12

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

  • Біжи FLUSH TABLES WITH READ LOCK
  • Зробіть знімок ZFS
  • Біжи UNLOCK TABLES

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

Інша проблема, яка у мене є, я планував зробити щось подібне mysql -h"$HOST" -u"$USERNAME" -p"$PASSWORD" --execute="FLUSH TABLES WITH READ LOCK". Однак це скидає блокування відразу після завершення сеансу. Це має сенс, але також дуже дратує, оскільки мені потрібно тримати блокування читання, коли я знімаю знімок.

Моя інша ідея - це зробити гарячу резервну копію за допомогою такого інструменту, як Percona XtraBackup, і зробити знімки резервної копії, але я не вважаю за краще платити кошти, щоб записати всі мої дані у друге місце лише для того, щоб зробити знімок.


Чому є статичний список таблиць? Ви, безумовно, можете генерувати список динамічно під час виконання.
ЄЕАА

1
Це база даних на VM чи на голому металі? Є сховище навіть на одній машині?
Майкл Хемптон

EEAA, досить справедливо.
Енді Шульман,

Майкл, база даних та поле ZFS - це різні машини, але жодна з них не віртуалізована.
Енді Шульман

@AndyShulman Я думаю, ви повинні пояснити макет трохи краще. Це не має сенсу.
ewwhite

Відповіді:


4

Якщо ви використовуєте InnoDB лише для всіх таблиць і встановите innodb_flush_log_at_trx_commit:

  • 1 (вміст буфера журналів InnoDB виписується у файл журналу при кожному здійсненні транзакції, а файл журналу передається на диск) або,
  • 2 (вміст буфера журналів InnoDB записується у файл журналу після кожної транзакції, а файл журналу видається на диск приблизно раз на секунду),

тоді вам не знадобляться СПІЛЬНІ ТАБЛИЦІ, перш ніж робити знімок, просто запустіть знімок ZFS безпосередньо. InnoDB може відновити дані з журналів фіксації транзакцій без втрати даних.

Посилання: https://dev.mysql.com/doc/refman/5.5/uk/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit


Із словником даних, введеним в MySQL 8, навіть операції DDL (модифікація схеми) тепер є атомними. До цього операції DDL під час зйомки файлової системи могли дати частково віддані (тобто пошкоджені) результати.
bernie

13

Вам потрібно повне блокування бази даних, щоб послідовно створювати резервні копії (більшості) баз даних.

У посібнику https://dev.mysql.com/doc/refman/5.5/en/backup-methods.html сказано, що ПОЛІТИ ТАБЛИЦІ З ЧИТАТИ БЛОКУ є правильним для знімків ZFS.

Створення резервних копій за допомогою знімка файлової системи

Якщо ви використовуєте файлову систему Veritas, ви можете зробити резервну копію таким чином:

  1. З клієнтської програми виконати FLUSH TABLES WITH READ LOCK.
  2. З іншої оболонки виконати vxfsзнімок монтажу .
  3. Від першого клієнта виконати UNLOCK TABLES.
  4. Скопіюйте файли із знімка.
  5. Демонтуйте знімок.

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

Смішно, що вони не враховували те, що вам потрібно FLUSH TABLES table_a, table_b, table_c FOR EXPORTдля InnoDB з цих інструкцій. Також нерозумно вказувати кожну таку таблицю. Але як говорить EEAA, ви можете створити список таблиць, коли ви починаєте резервне копіювання досить легко.

Що стосується утримування блокування, то під час виконання знімка потрібно підтримувати активне з'єднання db

Як правило, я б використовував щось на зразок Perl або іншу мову програмування, яка може підключити, заблокувати db і, зберігаючи db-з'єднання, зробити знімок, потім розблокувати та відключити. Це не складно. Я б зробив ставку, що там є інструменти, які вже роблять це, але писати їх легко.

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


Я сподівався зберегти такий концептуально простий сценарій у Bash, але ви правильно перемикання мов робить це набагато простіше. Я можу читати вашу відповідь неправильно, але, схоже, ви говорите, що мені потрібно виконати і те, FLUSH TABLES WITH READ LOCKі тоді FLUSH TABLES...FOR EXPORT, тоді як моє читання посібника MySQL говорить, що потрібно лише одне.
Енді Шульман

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

1
Зважаючи на те, що документація не дуже чітка, всю базу даних потрібно заблокувати, і що під час зйомки знімка необхідно підтримувати з'єднання БД, здається, простіше просто закрити БД, створити резервну копію та перезапустити. це.
Ендрю Генле

2
@andrew зітхнув ... Я розумію. Але це буде повільно, спричиняти відмову / вихід з ладу, і я бачив, що це може призвести до неправильного відновлення баз даних (погано для автоматизації). Було б добре отримати остаточну відповідь від mysql / Oracle. Вони повинні мати список розсилки.
Райан Бабчишин

7

Я зірвав і адаптував концептуально простий сценарій у Bash, який я знайшов в іншому повідомленні про помилку сервера від 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повинен бути доступний обом машинам, що ви повинні зробити досить легко, оскільки вони можуть отримати доступ до загального набору даних (хоча вони можуть використовувати різні шляхи, і ви повинні це врахувати).


Я не знаю сценаріїв MySQL, тому це може бути дурною ідеєю, але чи не могли ви просто зробити system zfs snapshot...всередині основного сценарію? Або озброєння має виконуватися в окремому процесі?
TripeHound

@Tripehound обидва речі повинні відбуватися паралельно
Ryan Babchishin

@RyanBabchishin Я думаю, що він прав, насправді. SYSTEMКоманда запускає речі локально. Якщо я запускаю mysql-клієнт у вікні FreeBSD і виконую LOCK; SYSTEM zfs snapshot; UNLOCK, то, здається, він би працював.
Енді Шульман

@Andy я щойно сказав, що вони повинні відбуватися паралельно. Не має значення, як ти йдеш про це.
Райан Бабчишин

2

Вам потрібні СТІЛКИ ТАБЛИЦІ З ПРОЧИТАНОЮ БЛОКУ для myisam, оскільки це не журнал.

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

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


2

Це моє рішення, як створити знімок ZFS, зберігаючи замок:

mysql << EOF
    FLUSH TABLES WITH READ LOCK;
    system zfs snapshot data/db@snapname
    UNLOCK TABLES;
EOF
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.