it-swarm.dev

Jak mogę zoptymalizować mysqldump dużej bazy danych?

Mam aplikację symfony z bazą danych InnoDB, która jest ~ 2 GB z 57 tabelami. Większość wielkości bazy danych znajduje się w jednej tabeli (~ 1,2 GB). Obecnie używam mysqldump do tworzenia kopii zapasowych bazy danych co noc.

Z powodu mojego połączenia Comcast, często jeśli ręcznie uruchamiam zrzut, moje połączenie z serwerem kończy się przed zakończeniem zrzutu, co powoduje, że muszę go ponownie uruchomić. [Obecnie uruchamiam crona, który wykonuje zrzut w nocy, to tylko dla zrzutów, które uruchamiam ręcznie.]

Czy istnieje sposób na przyspieszenie zrzutów w związku z przekroczeniem limitu czasu połączenia, ale także ograniczenie czasu zajmowanego przez serwer z tym procesem?

BTW, obecnie pracuję nad zmniejszeniem wielkości ogólnej bazy danych, aby rozwiązać ten problem.

179
Patrick

Głównym wąskim gardłem tego zrzutu jest napęd I/O. Odczytujesz ładunek danych i zapisujesz je ponownie. Możesz to przyspieszyć na kilka sposobów:

  • Upewnij się, że dane wyjściowe są przesyłane na inny dysk (dyski) niż ten, na którym przechowywane są pliki bazy danych - to zrobi ogromną różnicę w przypadku wirujących dysków, ponieważ głowice napędów nie będą ciągle przesuwać się między lokalizacją, z której są odczytywane i lokalizację, w której jest zapisywany.
  • Dane wyjściowe mysqldump będą bardzo ściśliwe, więc jeśli nie możesz oddzielić danych wyjściowych od danych wejściowych, jak wspomniano powyżej, potokuj dane wyjściowe przez gzip lub podobny. Zmniejszy to ilość zapisywanego tekstu (zmniejsz więc ogólne obciążenie IO i ruch głowy) kosztem pewnego czasu procesora (który możesz mieć dużo wolnego na te czasy i tak).
  • Ponadto (podobnie jak zamiast kompresji) przekazuj dane wyjściowe za pomocą narzędzia potokowego (takiego jak pv ), które obsługuje duże bufory zapisu, aby grupować bloki zapisane na dyskach bardziej razem, ponownie, aby zmniejszyć efekt head - opóźnienie przenoszenia - to zrobi całkiem różnicę, jeśli użyjesz --quick opcja zmniejszenia wpływu RAM tworzenie kopii zapasowych dużych tabel).
  • Uruchom proces tworzenia kopii zapasowej tylko wtedy, gdy IO jest poza tym niskie).

Być może naprawiasz niewłaściwy problem: zamiast tego łatwiej jest rozwiązać problemy z połączeniami (chociaż zmniejszenie obciążenia we/wy narzuconego przez kopie zapasowe pomoże zmniejszyć wpływ, jaki wywierasz na innych użytkowników, więc i tak warto spróbować). Czy możesz uruchomić ręczne kopie zapasowe za pomocą screen (lub podobnych narzędzi, takich jak tmux )? W ten sposób, jeśli połączenie z serwerem zostanie zerwane, możesz po prostu ponownie połączyć się i ponownie dołączyć do sesji screen bez przerywania procesów.

Jeśli wysyłasz dane bezpośrednio przez połączenie (tzn. Uruchamiasz mysqldump na komputerze lokalnym na zdalnej bazie danych, więc zrzut pojawia się lokalnie), lepiej najpierw uruchom zrzut na serwerze, kompresując go w razie potrzeby, a następnie przesyłając dane w sieci za pomocą narzędzia (takiego jak rsync), które obsługuje przesyłanie częściowe, aby można było wznowić przesyłanie (zamiast restartowania), jeśli połączenie zostanie przerwane.

W ramach „zmniejszania wielkości ogólnej bazy danych w celu rozwiązania tego problemu” zgaduję, że duża część twoich danych się nie zmienia. Możesz być w stanie przenieść dużą część 1,2 Gb z tej głównej tabeli do innej i usunąć ją z tych, które zostały skopiowane przez wywołanie mysqldump. Nie musisz tworzyć kopii zapasowych tych danych za każdym razem, jeśli nigdy się nie zmieni. Dzielenie danych między tabelami i bazami danych w ten sposób jest zwykle określane jako partycjonowanie danych i może również pozwolić na rozłożenie danych i obciążenia we/wy na wiele dysków. Wysokiej klasy baza danych ma wbudowane wsparcie dla automatycznego partycjonowania, chociaż w mysql prawdopodobnie będziesz musiał to zrobić ręcznie i zmienić warstwę dostępu do danych, aby to uwzględnić.

Odchodzę od tematu dla tej witryny (więc prawdopodobnie powinieneś przejść do ServerFault lub SuperUser, aby zapytać, czy potrzebujesz więcej szczegółów): Jeśli wydajesz się tracić połączenia z powodu braku aktywności, sprawdź opcje na serwerze SSH i kliencie SSH, aby upewnij się, że pakiety podtrzymujące są włączone i wysyłane wystarczająco często. Jeśli widzisz spadki, nawet jeśli połączenie jest aktywne, możesz również spróbować użyć OpenVPN lub podobnego do zawinięcia połączenia - powinien on obsłużyć krótki spadek, a nawet całkowity spadek, jeśli całe połączenie zostanie zerwane na kilka sekund, tak że klient SSH i serwer nie zauważa.

139
David Spillett

Wgląd w tworzenie kopii zapasowych za pomocą mysqldump

Tworzenie kopii zapasowych IMHO stało się bardziej formą sztuki, jeśli wiesz, jak się do tego zbliżyć

Masz opcje

Opcja 1: mysqldump całą instancję mysql

To jest najłatwiejsze, bez myślenia !!!

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

Wszystko zapisane w jednym pliku: struktury tabel, indeksy, wyzwalacze, procedury składowane, użytkownicy, zaszyfrowane hasła. Inne opcje mysqldump mogą również eksportować różne style poleceń INSERT, plik dziennika i współrzędne pozycji z dzienników binarnych, opcje tworzenia bazy danych, częściowe dane (opcja --where) i tak dalej.

Opcja 2: mysqldump oddzielne bazy danych w osobne pliki danych

Zacznij od utworzenia listy baz danych (w tym celu 2 techniki)

Technika 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

Technika 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

Technika 1 to najszybszy sposób. Technika 2 jest najpewniejsza i najbezpieczniejsza. Technika 2 jest lepsza, ponieważ czasami użytkownicy tworzą foldery do ogólnych celów w/var/lib/mysql (datadir), które nie są powiązane z bazą danych. Information_schema zarejestruje folder jako bazę danych w tabeli information_schema.schemata. Technika 2 pomija foldery, które nie zawierają danych mysql.

Po skompilowaniu listy baz danych możesz przejść do jej przeglądania i mysqldump, nawet jeśli to konieczne, równolegle.

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

Jeśli istnieje zbyt wiele baz danych, aby uruchomić je jednocześnie, zrzuć je równolegle 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

Opcja 3: mysqldump oddzielne tabele w osobne pliki danych

Zacznij od utworzenia listy tabel

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

Następnie zrzuć wszystkie tabele w grupach po 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

Opcja 4: WYKORZYSTAJ WYOBRAŹNIĘ

Wypróbuj odmiany wyżej wymienionych Opcji oraz techniki czyszczenia migawek

Przykłady

  1. Uporządkuj listę tabel według wielkości każdej tabeli rosnąco lub malejąco.
  2. Używając osobnego procesu, uruchom „FLUSH TABLES WITH READ LOCK; SELECT SLEEP (86400)” przed uruchomieniem mysqldumps. Zabij ten proces po zakończeniu mysqldumps. Jest to przydatne, jeśli baza danych zawiera zarówno InnoDB, jak i MyISAM
  3. Zapisz mysqldumps w datowanych folderach i obróć stare foldery kopii zapasowych.
  4. Załaduj mysqldumps całej instancji do samodzielnych serwerów.

[~ # ~] zastrzeżenie [~ # ~]

Tylko opcja 1 przynosi wszystko. Wadą jest to, że mysqldump utworzone w ten sposób można przeładować tylko do tej samej wersji mysql wydania Majot, w której został wygenerowany mysqldump. Innymi słowy, nie można załadować mysqldump z bazy danych MySQL 5.0 w wersji 5.1 lub 5.5. Powód ? Schemat mysql jest zupełnie inny wśród głównych wydań.

Opcje 2 i 3 nie obejmują zapisywania nazw użytkowników i haseł.

Oto ogólny sposób na zrzucenie Grantów SQL dla użytkowników, który jest czytelny i bardziej przenośny

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

Opcja 3 nie zapisuje procedur przechowywanych, więc możesz wykonać następujące czynności

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

Inną kwestią, na którą należy zwrócić uwagę, jest InnoDB. Jeśli masz dużą pulę buforów InnoDB, opróżnij ją najlepiej, jak potrafisz, przed wykonaniem jakichkolwiek kopii zapasowych. W przeciwnym razie MySQL spędza czas na opróżnianiu tabel z resztek brudnej strony z puli buforów. Oto, co sugeruję:

Na około godzinę przed wykonaniem kopii zapasowej uruchom to polecenie SQL

SET GLOBAL innodb_max_dirty_pages_pct = 0;

W MySQL 5.5 domyślna wartość innodb_max_dirty_pages_pct wynosi 75. W MySQL 5.1 i starszych domyślna wartość innodb_max_dirty_pages_pct wynosi 90. Ustawienie wartości innodb_max_dirty_pages_pct na 0 przyspieszy opróżnianie brudnych stron na dysk. Zapobiegnie to lub przynajmniej zmniejszy wpływ czyszczenia niekompletnych dwufazowych zatwierdzeń danych InnoDB przed wykonaniem jakiegokolwiek mysqldump w stosunku do jakichkolwiek tabel InnoDB.

OSTATECZNE Słowo NA mysqldump

Większość ludzi unika mysqldump na rzecz innych narzędzi i te narzędzia są naprawdę dobre.

Takie narzędzia obejmują

  1. MAATKIT (równoległe zrzut / przywróć skrypty, z Percona [Przestarzałe, ale świetne])
  2. XtraBackup (TopNotch Snapshot Backup from Percona)
  3. CDP R1Soft ( Opcja modułu MySQL , który wykonuje migawki w czasie)
  4. MySQL Enterprise Backup (poprzednio InnoDB Hot Backups [komercyjny])

Jeśli masz ducha prawdziwego MySQL DBA, możesz objąć mysqldump i mieć nad nim pełną biegłość. Niech wszystkie twoje kopie zapasowe będą odzwierciedleniem twoich umiejętności jako MySQL DBA .

122
RolandoMySQLDBA

Spójrz na master replikacji MySQL na slave. Pozwala sklonować bazę danych master na innym serwerze bazy danych z tą samą bazą danych. Obejmuje to tożsamość master i slave. Slave tworzy dokładną kopię głównego serwera bazy danych i/lub jego baz danych. Pomiędzy panem (-ami) i niewolnikiem (-ami) może istnieć relacja jeden-jeden, jeden-wiele, wiele-jeden.

Slave stale odczytuje dziennik binarny w master (bin bin przechowuje zapytania zapisane na głównym serwerze bazy danych) i pobiera dane wejściowe do swojego serwera slave bazy danych. (oznacza to, że nie będzie to miało wpływu na twoją główną bazę danych)

Dobra wiadomość jest taka, że ​​nie wpłynie to zbytnio na twój serwer MySQL, ponieważ nie zauważysz żadnych przestojów ani powolnych odpowiedzi na zapytania. Używamy go do baz danych 10 Gb i działa jak urok bez żadnych przestojów.

Replikacja MySQL na tej samej maszynie

20
poelinca

Plan A: Zobacz także Xtrabackup z Percona. Umożliwia to tworzenie kopii zapasowych InnoDB online bez znaczącego blokowania.

Plan B: Slave można zatrzymać i można wykonać spójną kopię zapasową na kilka sposobów (kopiowanie plików, mysqldump, xtrabackup itp.)

Plan C: Migawka LVM. Po pewnej tajemniczej konfiguracji czas przestoju dla kopii zapasowej wynosi mniej niż minutę, niezależnie od wielkości bazy danych. Zatrzymujesz mysqld, robisz migawkę, restartujesz mysqld, a następnie kopiujesz migawkę. Ostatni krok może zająć dużo czasu, ale MySQL nie działa.

Plan D: Migawka niewolnika - zero przestojów.

19
Rick James

Najpierw kilka punktów administratora: czy łączysz się, aby zrobić ftp, czy jesteś zalogowany i umiera? Jeśli ssh, to użyj screen, abyś mógł wznowić po awarii comcast. Jeśli ftp, to upewnij się, że kompresujesz/tar przed wysłaniem.

Spróbuj także parametru --opt lub --quick

--opt Ta opcja włącza zestaw dodatkowych opcji, aby usprawnić operacje zrzutu i przeładowania. W szczególności jest to równoważne z jednoczesnym stosowaniem opcji --add-drop-table, --add-locks, --all, --quick, --extended-insert, --lock-tables i --disable-keys. Zauważ, że ta opcja sprawia, że ​​dane wyjściowe są mniej przenośne i mniej prawdopodobne, że zostaną zrozumiane przez inne systemy baz danych.

--quick Ta opcja informuje mysqldump, aby zapisał dane zrzutu, gdy odczytuje każdy wiersz z serwera, co może być przydatne w przypadku dużych tabel. Domyślnie mysqldump czyta wszystkie wiersze z tabeli do pamięci przed zapisaniem danych wyjściowych; w przypadku dużych tabel wymaga to dużej ilości pamięci, co może spowodować niepowodzenie zrzutu.

15
David Hall

Miałem problemy z przekroczeniem limitu czasu również podczas zrzutów dużych baz danych. W końcu rozwiązałem, jeśli wysyłając indywidualne polecenia dla każdej tabeli w bazie danych i dołączając wszystko do jednego pliku w następujący sposób:

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
5
Patrick Heck

Myślę, że pytanie dotyczy tego, jak szybciej przywracać z plików zrzutu utworzonych przez mysqldump, a nie innego rozwiązania do tworzenia kopii zapasowych.

Jednym ze sposobów, w jaki można to zrobić, jest utworzenie grup tabel w schemacie i utworzenie osobnego użytkownika DB dla każdej grupy, a następnie użycie uprawnień MySQL, aby nie zezwalać na wstawianie tabel z użyciem tylko jednego użytkownika DB.

Jest to sprawdzona, szybka, prawie równoległa technika, ale nie w 100% pewna, ile czasu zajmie przywrócenie z dużych zrzutów, takich jak 500G lub mniej więcej. Ale moim skromnym zdaniem potrzebujesz czegoś równoległego. Sprawdź poniższy link jako przykład.

[Szybkie, równoległe przywracanie ze zrzutów SQL (mysqldump) dla MySQL] [1]

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

„Szybkie, równoległe przywracanie ze zrzutów SQL (mysqldump) dla MySQL”

3
syed