Как я могу оптимизировать mysqldump большой базы данных?

173

У меня есть приложение Symfony с базой данных InnoDB, ~ 2 ГБ с 57 таблицами. Большая часть размера базы данных находится в одной таблице (~ 1,2 ГБ). В настоящее время я использую mysqldump для резервного копирования базы данных каждую ночь.

Из-за моего comcast-соединения, часто, если я запускаю дамп вручную, мое соединение с сервером истекает до того, как дамп будет завершен, и мне придется повторно запускать дамп. [В настоящее время я запускаю cron, который выполняет дамп ночью, это только для дампов, которые я запускаю вручную.]

Есть ли способ ускорить дамп для проблемы времени ожидания соединения, но также и ограничить время, которое сервер занят этим процессом?

Кстати, я в настоящее время работаю над уменьшением размера всей базы данных, чтобы решить эту проблему.

Патрик
источник
2
Какие параметры (если они есть) вы передаете команде mysqldump?
Тоби
Добавление --compact может быть вариантом для вас.
Тоби
ничего на самом деле -mysqldump [database] -u[user] -p'[password]' > db_backup.sql
Патрик
4
Простой альтернативой screenдля вашей ситуации будет использование nohup, это позволит вашей команде продолжать работать на сервере, даже если ваше соединение будет разорвано. Например nohup mysqldump [options] > backup.sql 2> backup.err &. Если вы не предоставите выходной файл nohup, он будет создан nohup.outпо умолчанию.
dabest1
1
Посмотрите atи screen(последний atвариант, если он установлен, но является стандартным для всех юниксов) или ServerAliveIntervalварианты SSH для способов работы с брандмауэром, закрывающим вас после слишком долгого простоя соединения.
MattBianco

Ответы:

134

Основным узким местом в этом дампе является дисковый ввод-вывод. Вы читаете множество данных и записываете их снова. Вы можете ускорить это несколькими способами:

  • Убедитесь, что ваши выходные данные идут на другой диск (и), чем тот, на котором хранятся файлы базы данных - это будет иметь огромное значение для вращающихся дисков, так как головки дисков не будут постоянно переключаться между местом чтения из и место написания для.
  • Выходные данные mysqldump будут очень сжимаемыми, поэтому, если вы не можете отделить выходные данные от входных данных, как упомянуто выше, передайте выходные данные gzipили аналогичные. Это уменьшит объем выполняемой записи (таким образом, уменьшит общую нагрузку ввода-вывода и количество движений головы) за счет некоторого времени ЦП (которое в любом случае может быть достаточно большим).
  • Кроме того (или вместо сжатия) передайте вывод через утилиту конвейера (например, pv ), которая поддерживает большие буферы записи, чтобы еще больше сгруппировать блоки, записываемые на диски, снова, чтобы уменьшить эффект задержки движения головы - это сделает большая разница, если использовать --quickопцию для уменьшения влияния ОЗУ на резервное копирование больших таблиц).
  • Запускайте процесс резервного копирования только тогда, когда нагрузка ввода-вывода будет низкой.

Возможно, вы решаете не ту проблему: вместо этого может быть проще устранить разрывы соединения (хотя снижение нагрузки ввода-вывода, создаваемой вашими резервными копиями, поможет уменьшить влияние, которое вы оказываете на других пользователей, поэтому стоит попробовать в любом случае). Не могли бы вы выполнить резервное копирование вручную через экран (или аналогичные инструменты, такие как tmux )? Таким образом, если ваше соединение с сервером обрывается, вы можете просто повторно подключиться и подключиться к screenсеансу без прерывания каких-либо процессов.

Если вы отправляете данные напрямую по соединению (то есть запускаете mysqldump на своей локальной машине с удаленной базой данных, поэтому дамп отображается локально), лучше сначала выполнить дамп на сервере, сжимая при необходимости, затем передавая данные по сети, используя инструмент (такой как rsync), который поддерживает частичные передачи, так что вы можете возобновить передачу (вместо перезапуска), если разрыв соединения прерывает его.

В рамках вашего «уменьшения размера всей базы данных для решения этой проблемы» я бы предположил, что большая часть ваших данных не изменится. Возможно, вам удастся переместить большой кусок 1.2 Гб из этой основной таблицы в другую и удалить его из тех, которые копируются mysqldumpвызовом. Вам не нужно каждый раз резервировать эти данные, если они никогда не изменятся. Разделение данных между таблицами и базами данных таким способом обычно называется разделением данных и может также позволить вам распределить данные и нагрузку ввода-вывода по нескольким дискам. Высококачественная база данных имеет встроенную поддержку автоматического разбиения, хотя в mysql вам, вероятно, придется делать это вручную и изменять свой уровень доступа к данным, чтобы учесть это.

Отклонение от темы для этого сайта (так что вам, вероятно, следует перейти к ServerFault или SuperUser, чтобы узнать, нужны ли вам более подробные сведения): если вам кажется, что соединения теряются из-за неактивности, проверьте параметры на вашем SSH-сервере и SSH-клиенте, чтобы сделать пакеты keep-alive включены и отправляются достаточно часто. Если вы видите пропадание, даже если соединение активно, вы также можете попробовать использовать OpenVPN или аналогичный для обертывания соединения - оно должно обрабатывать короткое сбрасывание, даже полное сбрасывание, если все ваше соединение не работает в течение нескольких секунд, так что клиент SSH и Сервер не замечает.

Дэвид Спиллетт
источник
Я хотел бы уменьшить количество сброшенных соединений SSH с моими серверами. Если я ожидаю, что не буду использовать терминал дольше ~ 60 секунд, я запускаю, topчтобы убедиться, что соединение не прерывается. (И я уверен, что это соединение comcast, так как мы используем только стандартный маршрутизатор WRT и брандмауэр на работе, и мое домашнее соединение comcast никогда не прерывается)
Патрик
Я добавил короткую заметку, относящуюся к соединениям SSH.
Дэвид Спиллетт
2
Глубина и понимание в этом ответе. Вы должны получить +3 за это. Извините, я могу дать вам только +1.
RolandoMySQLDBA
116

Проницательность в создание резервных копий с mysqldump

ИМХО Создание резервных копий стало больше искусством, если вы знаете, как к нему подойти

У вас есть варианты

Вариант 1: mysqldump весь экземпляр mysql

Это самый простой, ежу понятно !!!

mysqldump -h... -u... -p... --hex-blob --routines --triggers --all-databases | gzip > MySQLData.sql.gz

Все записано в одном файле: структуры таблиц, индексы, триггеры, хранимые процедуры, пользователи, зашифрованные пароли. Другие параметры mysqldump также могут экспортировать различные стили команд INSERT, файла журнала и координат положения из двоичных журналов, параметров создания базы данных, частичных данных (параметр --where) и т. Д.

Вариант 2: mysqldump отдельные базы данных в отдельные файлы данных

Начните с создания списка баз данных (2 метода для этого)

Техника 1

mysql -h... -u... -p... -A --skip-column-names -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql')" > ListOfDatabases.txt

Техника 2

mysql -h... -u... -p... -A --skip-column-names -e"SELECT DISTINCT table_schema FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql')" > ListOfDatabases.txt

Техника 1 - самый быстрый способ. Техника 2 самая надежная и безопасная. Техника 2 лучше, потому что иногда пользователи создают папки общего назначения в / var / lib / mysql (datadir), которые не связаны с базой данных. Information_schema будет регистрировать папку в качестве базы данных в таблице information_schema.schemata. Метод 2 будет обходить папки, которые не содержат данных mysql.

После того, как вы скомпилируете список баз данных, вы можете перейти к циклу по списку и mysqldump их, даже параллельно, если это необходимо.

for DB in `cat ListOfDatabases.txt`
do
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz &
done
wait

Если за один раз слишком много баз данных, параллельный дамп их по 10 за раз:

COMMIT_COUNT=0
COMMIT_LIMIT=10
for DB in `cat ListOfDatabases.txt`
do
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz &
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

Вариант 3: mysqldump отдельные таблицы в отдельные файлы данных

Начните с создания списка таблиц

mysql -h... -u... -p... -A --skip-column-names -e"SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql')" > ListOfTables.txt

Затем сбросьте все таблицы в группы по 10

COMMIT_COUNT=0
COMMIT_LIMIT=10
for DBTB in `cat ListOfTables.txt`
do
    DB=`echo ${DBTB} | sed 's/\./ /g' | awk '{print $1}'`
    TB=`echo ${DBTB} | sed 's/\./ /g' | awk '{print $2}'`
    mysqldump -h... -u... -p... --hex-blob --triggers ${DB} ${TB} | gzip > ${DB}_${TB}.sql.gz &
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

Вариант 4: используйте ваше воображение

Попробуйте варианты вышеупомянутых опций плюс методы для получения чистых снимков

Примеры

  1. Упорядочить список таблиц по размеру каждой таблицы по возрастанию или убыванию.
  2. Используя отдельный процесс, запустите «FLUSH TABLES WITH READ LOCK; SELECT SLEEP (86400)» перед запуском mysqldumps. Убейте этот процесс после завершения mysqldumps. Это полезно, если база данных содержит как InnoDB, так и MyISAM.
  3. Сохраните mysqldumps в устаревших папках и разверните старые резервные папки.
  4. Загрузите весь экземпляр mysqldumps на автономные серверы.

ПРЕДОСТЕРЕЖЕНИЕ

Только Вариант 1 приносит все. Недостатком является то, что mysqldumps, созданные таким образом, могут быть перезагружены только в ту же версию релиза mysql, которая была сгенерирована mysqldump. Другими словами, mysqldump из базы данных MySQL 5.0 не может быть загружен в 5.1 или 5.5. Причина ? Схема mysql полностью отличается в основных выпусках.

Варианты 2 и 3 не включают сохранение имен пользователей и паролей.

Вот общий способ выгрузки SQL-грантов для пользователей, который удобочитаем и более переносим

mysql -h... -u... -p... --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql -h... -u... -p... --skip-column-names -A | sed 's/$/;/g' > MySQLGrants.sql

Вариант 3 не сохраняет хранимые процедуры, поэтому вы можете сделать следующее

mysqldump -h... -u... -p... --no-data --no-create-info --routines > MySQLStoredProcedures.sql &

Еще один момент, который следует отметить, касается InnoDB. Если у вас большой пул буферов InnoDB, имеет смысл очистить его как можно лучше перед выполнением любых резервных копий. В противном случае MySQL тратит время на очистку таблиц с оставшейся грязной страницей из пула буферов. Вот что я предлагаю:

Примерно за 1 час до выполнения резервного копирования запустите эту команду SQL

SET GLOBAL innodb_max_dirty_pages_pct = 0;

В MySQL 5.5 по умолчанию значение innodb_max_dirty_pages_pct равно 75. В MySQL 5.1 и более поздних версиях по умолчанию значение innodb_max_dirty_pages_pct равно 90. Если для параметра innodb_max_dirty_pages_pct задано значение 0, это ускорит сброс грязных страниц на диск. Это предотвратит или, по крайней мере, уменьшит влияние очистки любых неполных двухфазных фиксаций данных InnoDB перед выполнением любого mysqldump для любых таблиц InnoDB.

ЗАКЛЮЧИТЕЛЬНОЕ СЛОВО НА mysqldump

Большинство людей уклоняются от mysqldump в пользу других инструментов, и эти инструменты действительно хороши.

Такие инструменты включают

  1. MAATKIT (параллельные скрипты дампа / восстановления от Percona [устарело, но великолепно])
  2. XtraBackup (резервное копирование снимка TopNotch от Percona)
  3. CDP R1Soft ( опция модуля MySQL, которая делает моментальные снимки времени)
  4. MySQL Enterprise Backup (ранее горячее резервное копирование InnoDB [коммерческое])

Если у вас есть дух настоящего администратора баз данных MySQL, вы можете использовать mysqldump и полностью овладеть им. Пусть все ваши резервные копии будут отражать ваши навыки в качестве администратора баз данных MySQL .

RolandoMySQLDBA
источник
2
+1 для хорошего использования mysqldump, а также для: Если у вас есть дух настоящего DBA MySQL, вы можете принять mysqldump и иметь полное мастерство над ним, которое может быть достигнуто. Пусть все ваши резервные копии будут отражением ваших навыков администратора базы данных MySQL .... Великолепные линии !!!
Абдул Манаф
4
В InnoDB, дамп таблицы по отдельности даст вам противоречивую резервную копию.
Ален Коллинз
5
@AlainCollins, поэтому я запускаю mysqldumps на подчиненном устройстве репликации, которое доступно только для чтения. Если Seconds_Behind_Master равен 0, вы запускаете STOP SLAVE. Теперь у вас есть согласованный момент времени для выполнения mysqldumps в любом из вышеупомянутых стилей. За последние 5 лет я сделал это для компаний, занимающихся онлайн-торговлей, без единой жалобы ни мне, ни владельцам моей компании. На данный момент я делаю параллельные mysqldumps каждые 10 минут для этого клиента. Я также делаю это для других клиентов, чтобы обеспечить более быстрые периоды резервного копирования.
RolandoMySQLDBA
У меня 32 ГБ, поэтому вариант 3 - это именно то, что я имел в виду! Спасибо!
Раймонд
Я должен сделать резервную копию и повторно импортировать 1 ТБ данных, чтобы сжать очень большой ibdata1. Во времена SSD, поддерживаемых аппаратным RAID, вариант 3 - единственное решение для меня.
Рабудде
18

Взгляните на мастер репликации MySQL, чтобы подчинить. Это позволяет вам клонировать базу данных master на другой сервер базы данных с той же базой данных. Это включает в себя ведущие и ведомые личности. Ведомый делает себя точной копией главного сервера базы данных и / или его баз данных. Может быть отношение один-один, один-много, много-один между хозяином (ами) и рабом (ами).

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

Хорошая новость заключается в том, что это не сильно повлияет на ваш сервер MySQL, так как вы не заметите простоев или медленных ответов на запросы. Мы используем его для баз данных 10 Гб, и он работает как шарм без каких-либо простоев.

Репликация MySQL на той же машине

poelinca
источник
хотя это будет работать для меня, я думаю, что это может быть немного излишним. В настоящее время мне не нужен такой уровень резервного копирования, хотя я буду помнить об этом, если требования приложения изменятся.
Патрик
4
+1 за резервное копирование реплики для удаления нагрузки ввода-вывода резервной копии из основной БД и уменьшения потенциальных проблем, связанных с блокировкой, с одним существенным предостережением: будьте осторожны с опцией «реплика на том же компьютере», что и операции на ведомом устройстве может конкурировать с ведущим за пропускную способность ввода-вывода - убедитесь, что файлы данных ведомого устройства отличаются от диска / массива, чем ведущий, чтобы смягчить эту проблему.
Дэвид Спиллетт
1
То же самое касается комментария Дэвида Спллета. Я устанавливаю и поддерживаю десятки главных / подчиненных с резервными копиями mysqldump на подчиненных для My Web Hosting Employer. +1 от меня тоже.
RolandoMySQLDBA
16

План A: См. Также Xtrabackup от Percona. Это позволяет оперативное резервное копирование InnoDB, без каких-либо значительных блокировок.

План B: Ведомый может быть остановлен, и вы можете сделать последовательное резервное копирование любым из нескольких способов (копирование файлов, mysqldump, xtrabackup и т. Д.)

План C: Снимок LVM. После некоторой загадочной настройки время простоя резервной копии составляет менее минуты, независимо от размера базы данных. Вы останавливаете mysqld, делаете снимок, перезапускаете mysqld, а затем копируете снимок. Последний шаг может занять много времени, но MySQL не работает.

План D: Снимок раба - нулевое время простоя.

Рик Джеймс
источник
2
Ура всем четырем планам. Я могу дать только +0.25 за ответ !!! +1 (4 x 0,25)
RolandoMySQLDBA
15

Сначала несколько советов администратора: вы подключаетесь, чтобы сделать ftp, или вы ssh'ed, и он умирает? Если ssh, то обязательно используйте экран, чтобы вы могли возобновить работу после сбоя comcast. Если ftp, то перед отправкой убедитесь, что вы сжимаете его / tar.

Также попробуйте параметр --opt или --quick

--opt Этот параметр включает набор дополнительных параметров, чтобы сделать операции дампа и перезагрузки более эффективными. В частности, это эквивалентно совместному использованию опций --add-drop-table, --add-locks, --all, --quick, --extended-insert, --lock-tables и --disable-keys. Обратите внимание, что эта опция делает вывод менее переносимым и менее вероятным для понимания другими системами баз данных.

--quick Эта опция указывает mysqldump записывать вывод дампа при чтении каждой строки с сервера, что может быть полезно для больших таблиц. По умолчанию mysqldump читает все строки из таблицы в память перед записью вывода; для больших таблиц это требует больших объемов памяти, что может привести к сбою дампа.

Дэвид Холл
источник
1
Разве --opt не увеличит размер файла, который в итоге получит вывод?
Тоби
Это добавит немного - я хотел добавить --quick, который больше отвечает его проблеме ... редактирование сейчас. Спасибо!
Дэвид Холл
+1 за экран, который полностью устраняет эту проблему
Гай
+1 за очень хороший и краткий ответ за объяснения mysqldump --opt и --quick.
RolandoMySQLDBA
1
--opt включен по умолчанию.
Джордан
5

Раньше у меня были проблемы с тайм-аутами во время дампов больших баз данных. Я наконец-то решил, отправив отдельные команды для каждой таблицы в БД и добавив что-либо в один файл, например так:

TABLES=`mysql -u $USER -p$PWD -Bse 'show tables' $DB`
for TABLE in $TABLES
do
    mysqldump -u $USER -p$PWD $DB $TABLE >> dump.sql
done
Патрик Хек
источник
4
Это считается «несогласованной» резервной копией, поскольку при восстановлении в одной таблице могут быть данные, которые сопоставляются с другой, но не существуют.
Морган Токер
3

Я думаю, что вопрос в том, как восстановить быстрее из созданных файлов дампа mysqldump, а не в другом решении для резервного копирования.

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

Это проверенный, быстрый, почти параллельный метод, но он не уверен на 100%, сколько времени потребуется для восстановления из больших дампов типа 500G или около того. Но, по моему скромному мнению, тебе нужно что-то параллельное. Проверьте ссылку ниже для примера.

[Быстрое параллельное восстановление из дампов SQL (mysqldump) для MySQL] [1]

http://geeksww.com/tutorials/database_management_systems/mysql/tips_and_tricks/fast_parallel_restore_from_sql_dumps_mysqldump_for_mysql.php

«Быстрое параллельное восстановление из дампов SQL (mysqldump) для MySQL»

Сайед
источник
2
Это точная копия вашего ответа на другой вопрос. Возможно, вы захотите настроить его немного больше для этого конкретного вопроса.
Пол Уайт
Вопрос конкретно НЕ о том, как быстрее восстановить.
Андрей Лориен