Як я можу оптимізувати mysqldump великої бази даних?


173

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

Через моє з'єднання comcast, часто, якщо я запускаю дамп вручну, моє з'єднання з сервером закінчиться до закінчення дампа, що призведе до того, що мені доведеться повторно виконувати дамп. [Я зараз запускаю крон, який робить дамп щоночі, це лише для смітників, які я запускаю вручну.]

Чи є спосіб пришвидшити скидання для випуску тайм-ауту підключення, а також обмежити час, коли сервер зайнятий цим процесом?

BTW, я зараз працюю над зменшенням розміру загальної бази даних, щоб вирішити цю проблему.


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є стандартним для всіх Unixes) або ServerAliveIntervalваріантів SSH для способів роботи з брандмауером закриваючи вас вниз після занадто довгого простою з'єднання.
MattBianco

Відповіді:


134

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

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

Ви можете виправити помилкову проблему: натомість вирішити краплі з'єднання може бути простіше (хоча зменшення навантаження вводу / виводу, накладене вашими резервними копіями, допоможе зменшити вплив, який ви маєте на інших користувачів, тому варто все-таки спробувати). Чи можете ви виконати резервні копії вручну через екран (або подібні інструменти, такі як tmux )? Таким чином, якщо ваше з’єднання з сервером перестане, ви можете просто підключитися та повторно підключитись до screenсеансу без жодних процесів.

Якщо ви надсилаєте дані безпосередньо через з'єднання (тобто ви запускаєте mysqldump на вашій локальній машині проти віддаленої бази даних, тому дамп з’являється локально), вам може бути краще спершу запустити дамп на сервері, стискаючи, якщо потрібно, а потім перенести дані через мережу, використовуючи інструмент (наприклад rsync), який підтримує часткові передачі, щоб ви могли відновити передачу (замість перезавантаження), якщо падіння з'єднання перериває її.

Як частина вашого "зменшення розміру загальної бази даних для вирішення цієї проблеми", я б припустив, що великий фрагмент ваших даних не змінюється. Можливо, ви зможете перенести великий фрагмент 1,2Gb з цієї основної таблиці в інший і видалити його з тих, що скопійовані mysqldumpвикликом. Вам не потрібно робити резервні копії цих даних кожного разу, якщо вони ніколи не змінюються. Розбиття даних між таблицями та базами даних таким чином зазвичай називають розділенням даних і може також дозволяти поширювати дані та завантажувати введення / виведення на декілька накопичувачів. База даних високого класу має вбудовану підтримку автоматичного розділення, хоча в mysql вам, мабуть, доведеться це зробити вручну та змінити рівень доступу до даних, щоб врахувати це.

Відхилення від теми для цього сайту (тому, ймовірно, вам слід перейти на ServerFault або SuperUser, щоб запитати, чи потрібна вам детальніше): Якщо вам здається, що ви втрачаєте зв’язки через неактивність, перевірте параметри свого SSH-сервера та SSH-клієнта, щоб зробити переконайтеся, що пакети збереження ввімкнено і надсилаються досить часто. Якщо ви бачите краплі, навіть якщо з'єднання активне, ви також можете спробувати скористатися OpenVPN або подібним, щоб перетворити з'єднання - воно повинно працювати з коротким падінням, навіть повним падінням, якщо все ваше з'єднання буде на декілька секунд перервано, наприклад, щоб клієнт SSH та сервер не помічає.


Я б хотів, щоб я міг зменшити кількість перерваних ssh-з'єднань до моїх серверів. Якщо я сподіваюся не використовувати термінал довше ~ 60 секунд, я бігаю, topщоб з'єднання не перестало . (І я майже впевнений, що це з'єднання comcast, оскільки ми використовуємо лише стандартний WRT-роутер та брандмауер на роботі, і моє домашнє з'єднання ніколи не випадає)
Патрік

Я додав коротку примітку, специфічну для SSH-з'єднань.
Девід Спіллетт

2
Глибина та проникливість у цій відповіді. Ви повинні отримати +3 для цього. Вибачте, я можу дати вам лише +1.
RolandoMySQLDBA

116

ПОВЕРНІТЬСЯ, ЩО РОБИТИ РЕКЛАМИ З mysqldump

Резервне копіювання IMHO Doing стало більшою мірою мистецтвом, якщо ви просто знаєте, як до нього підійти

У вас є варіанти

Варіант 1: mysqldump цілий екземпляр mysql

Це найпростіший, безмозковий !!!

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

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

Варіант 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), які не пов'язані з базою даних. Інформація_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. Використовуючи окремий процес, перед запуском mysqldumps запустіть "ПРОМИСЛУВАННЯ ТАБЛИЦІ З ЧИТАННЯМ ЧИТАННЯ; ВИБІРТЕ СЛОП (86400)". Вбийте цей процес після завершення mysqldumps. Це корисно, якщо база даних містить і InnoDB, і MyISAM
  3. Збережіть mysqldumps у датованих папках та оберніть старі резервні папки.
  4. Завантажте весь екземпляр mysqldumps на автономні сервери.

КАВАТИ

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

Варіанти 2 і 3 не включають збереження імен користувачів та паролів.

Ось загальний спосіб скидання SQL Grants для користувачів, який читається та є більш портативним

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 витрачає час на промивання таблиць із залишкою брудної сторінки з буферного пулу. Ось що я пропоную:

Приблизно за годину до виконання резервного копіювання запустіть цю команду 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 (раніше гарячі резервні копії InnoDB [комерційний])

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


2
+1 для хорошого використання mysqldump, а також для: Якщо у вас є дух справжньої MySQL DBA, ви можете прийняти mysqldump і мати повне майстерність над цим, яке можна досягти. Нехай всі ваші резервні копії будуть відображенням ваших навичок як MySQL DBA .... Чудові лінії !!!
Абдул Манаф

4
У InnoDB демпінгові таблиці окремо дають вам непослідовне резервне копіювання.
Ален Коллінз

5
@AlainCollins, тому я запускаю mysqldumps на підлеглому реплікації, який читається тільки. Як тільки Seconds_Behind_Master дорівнює 0, ви запускаєте STOP SLAVE. Тепер у вас є послідовний момент часу для виконання mysqldumps у будь-якому з вищезгаданих стилів. Я робив це для компаній, що займаються торгівлею в Інтернеті, протягом останніх 5 років, без жодної скарги на мене або власників моєї компанії. З цього моменту я роблю паралельні mysqldumps кожні 10 хвилин для цього клієнта. Я також роблю це для інших клієнтів, щоб забезпечити більш швидкі періоди резервного копіювання.
RolandoMySQLDBA

У мене є 32 Гб дБ, тому варіант 3 - це саме те, що я мав на увазі! Дякую!
Реймонд

Мені потрібно створити резервну копію та повторний імпорт даних 1 ТБ, щоб зменшити надзвичайно велику кількість ibdata1. У часи SSD, підтримуваних апаратним RAID, варіант 3 є єдиним рішенням для мене.
rabudde

18

Погляньте на майстра реплікації MySQL на підлеглий. Це дозволяє клонувати базу даних master на інший сервер бази даних з тією ж базою даних. Сюди входять ідентичності господаря та раба. Slave створює точну копію головного сервера баз даних та або його баз даних. Можливе існування відносин один-один, один-багато-багато-одне серед господаря (-ів) і раба (-ів).

Slave постійно читає бінарний журнал у master (бін журнал зберігає запити, написані на майстер-сервері баз даних) і отримує вхід на його підлеглий сервер бази даних. (це означає, що ваша головна база даних взагалі не вплине)

Хороша новина полягає в тому, що це не вплине занадто сильно на ваш сервер MySQL, оскільки ви не помітите простоїв або повільних відповідей на запити. Ми використовуємо його для баз даних 10Gb, і він працює як шарм без простоїв.

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


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

4
+1 для створення резервної копії репліки для видалення завантаження резервної копії IO з основної БД та зменшення потенційних проблем, пов’язаних із блокуванням, з одним істотним застереженням: будьте обережні з опцією "репліка на тій же машині", що і ваші операції на підлеглому може конкурувати з ведучим за пропускну здатність IO - переконайтеся, що файли даних веденого пристрою є іншим приводом / масивом, ніж головний, щоб пом'якшити цю проблему.
Девід Спіллетт

1
Дітто на коментар Девіда Сплетта. Я налаштовую та підтримую десятки головних / рабів із резервними копіями mysqldump на рабах для мого роботодавця веб-хостингу. +1 також від мене.
RolandoMySQLDBA

16

План A: Дивіться також Xtrabackup від Percona. Це дозволяє здійснювати онлайн-резервне копіювання InnoDB без істотного блокування.

План B: Раб може бути зупинений, і ви можете зробити послідовне резервне копіювання будь-яким із кількох способів (копіювати файли, mysqldump, xtrabackup тощо)

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

План D: Знімок раба - нульовий час простою.


2
Хура всім чотирма планам. Я можу дати лише +0,25 за відповідь !!! +1 (4 х 0,25)
RolandoMySQLDBA

15

По-перше, декілька пунктів адміністрування: Ви підключаєтесь до того, щоб зробити ftp, або ви заграли, і він вмирає? Якщо ssh, тоді обов'язково використовуйте екран, щоб ви могли відновитись після аварії comcast. Якщо ftp, переконайтеся, що ви стискаєте його / tar перед відправленням.

Спробуйте також параметр --opt або --quick

--opt Ця опція вмикає набір додаткових опцій, щоб зробити операції скидання та перезавантаження більш ефективними. Зокрема, це еквівалентно використанню параметрів --add-drop, --add-locks, --all, --quick, --extended-insert, --lock-table та --disable-keys разом. Зауважте, що цей параметр робить вихід менш портативним і менш імовірно зрозумілий іншими системами баз даних.

--quick Цей параметр повідомляє mysqldump писати вихідний дамп під час читання кожного рядка з сервера, що може бути корисно для великих таблиць. За замовчуванням mysqldump зчитує всі рядки з таблиці в пам'ять перед тим, як записати вихід; для великих таблиць для цього потрібен великий об'єм пам'яті, що може спричинити збій дампа.


1
Чи не буде --opt не збільшувати розмір файлу, який з часом отримає вихід?
Тобі

Це додасть декілька - я мав на увазі додати - швидкий вибір, що відповідає на його проблему .... редагування зараз. Дякую!
Девід Холл

+1 для екрана, який взагалі уникає цієї проблеми
Гай

+1 - дуже приємна та лаконічна відповідь на пояснення mysqldump --opt та - - швидкі.
RolandoMySQLDBA

1
--opt увімкнено за замовчуванням.
Йордан

5

У мене раніше виникали проблеми з таймаутами під час скидання великих баз даних. Я нарешті вирішив, якщо надсилати окремі команди для кожної таблиці в db і додавати все до одного файлу, як це:

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
Це точна копія вашої відповіді на інше питання. Ви можете налаштувати його трохи більше для цього конкретного питання.
Пол Білий

Питання конкретно НЕ про те, як швидше відновити.
andrew lorien
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.