Come posso ottimizzare un mysqldump di un database di grandi dimensioni?


173

Ho un'applicazione symfony con un database InnoDB che è ~ 2 GB con 57 tabelle. La maggior parte delle dimensioni del database risiede in una singola tabella (~ 1,2 GB). Attualmente sto usando mysqldump per eseguire il backup del database ogni notte.

A causa della mia connessione comcast, spesso se eseguo un dump manualmente la mia connessione al server si interromperà prima che il dump sia completo, causandomi di dover rieseguire il dump. [Attualmente eseguo un cron che esegue il dump ogni notte, questo è solo per i dump che eseguo manualmente.]

C'è un modo per accelerare i dump per il problema di timeout della connessione, ma anche per limitare il tempo in cui il server è occupato con questo processo?

A proposito, attualmente sto lavorando per ridurre le dimensioni del database generale per risolvere questo problema.


2
Quali parametri (se presenti) stai passando al comando mysqldump?
Toby,

Aggiungendo --compact potrebbe essere un'opzione per te.
Toby,

niente di veramente -mysqldump [database] -u[user] -p'[password]' > db_backup.sql
Patrick

4
Una semplice alternativa a screenper la tua situazione sarebbe quella di utilizzare nohup, consentirà al tuo comando di continuare a funzionare sul server, anche se la tua connessione viene interrotta. Es nohup mysqldump [options] > backup.sql 2> backup.err &. Se non si fornisce un file di output per nohup, verrà creato nohup.outper impostazione predefinita.
dabest1,

1
Dai un'occhiata ate screen(quest'ultimo se installato, ma atè standard su tutti gli unix) o le ServerAliveIntervalopzioni per SSH per i modi di gestire il firewall che ti spegne dopo una connessione inattiva troppo lunga.
MattBianco,

Risposte:


134

Il principale collo di bottiglia nella discarica come questo è I / O dell'unità. Stai leggendo un carico di dati e riscrivendolo. Puoi accelerarlo in diversi modi:

  • Assicurati che il tuo output stia andando su una o più unità diverse da quelle su cui sono archiviati i file di database - questo farà una grande differenza con i dischi rotanti poiché le testine dell'unità non scorreranno costantemente tra la posizione da cui si sta leggendo e la posizione in cui si sta scrivendo.
  • L'output di mysqldump sarà molto comprimibile, quindi se non è possibile separare l'output dall'input come menzionato sopra, reindirizzare l'output gzipo simili. Ciò ridurrà la quantità di scrittura in corso (quindi riduci il carico di I / O generale e la quantità di movimento della testina) a scapito di un po 'di tempo della CPU (che potresti avere comunque molto tempo libero in questi momenti).
  • Inoltre, (come pure o invece della compressione), passa l'output attraverso un'utility pipe (come pv ) che supporta grandi buffer di scrittura per raggruppare più blocchi scritti sulle unità, ancora una volta per ridurre l'effetto della latenza del movimento della testa - questo renderà piuttosto una differenza se si utilizza l' --quickopzione per ridurre l'impatto RAM del backup di tabelle di grandi dimensioni).
  • Eseguire il processo di backup solo quando il carico di I / O è altrimenti basso.

È possibile che tu stia risolvendo il problema sbagliato: potrebbe invece essere più semplice affrontare le cadute di connessione (sebbene ridurre il carico di I / O imposto dai tuoi backup contribuirà a ridurre l'effetto che hai sugli altri utenti, quindi vale la pena provare comunque). Potresti eseguire i tuoi backup manuali attraverso lo schermo (o strumenti simili come tmux )? In questo modo se la connessione al server si interrompe, è possibile riconnettersi e ricollegarsi alla screensessione senza interrompere alcun processo.

Se stai inviando i dati direttamente tramite la connessione (ovvero stai eseguendo mysqldump sul tuo computer locale contro un database remoto, quindi il dump appare localmente) potresti essere meglio eseguendo prima il dump sul server, comprimendolo secondo necessità, quindi trasferendo i dati sulla rete utilizzando uno strumento (come rsync) che supporta i trasferimenti parziali in modo da poter riprendere il trasferimento (invece di riavviarlo) se una caduta di connessione lo interrompe.

Come parte del tuo "ridurre le dimensioni del database complessivo per risolvere questo problema", immagino che una grande parte dei tuoi dati non cambi. Potresti riuscire a spostare un grosso pezzo di 1.2Gb da quella tabella principale in un'altra e rimuoverla da quelle che sono state copiate dalla mysqldumpchiamata. Non è necessario eseguire il backup di questi dati ogni volta che non cambiano mai. La suddivisione dei dati tra tabelle e database in questo modo viene generalmente definita partizionamento dei dati e può anche consentire di distribuire i dati e il carico di I / O su più unità. Il database di fascia alta ha integrato il supporto per il partizionamento automatico, sebbene in mysql probabilmente dovrai farlo manualmente e modificare il tuo livello di accesso ai dati per tenerne conto.

Distaccarsi dall'argomento per questo sito (quindi probabilmente dovresti passare a ServerFault o SuperUser per chiedere se hai bisogno di maggiori dettagli): Se sembra che tu stia perdendo connessioni a causa di inattività, controlla le opzioni nel tuo server SSH e nel client SSH per effettuare certo che i pacchetti keep-alive sono abilitati e inviati abbastanza spesso. Se vedi i drop anche se la connessione è attiva, puoi anche provare a usare OpenVPN o simili per concludere la connessione: dovrebbe gestire un drop breve, anche un drop completo se l'intera connessione è inattiva per alcuni secondi, in modo che il client SSH e il server non se ne accorge.


Vorrei poter ridurre il numero di connessioni ssh eliminate ai miei server. Se mi aspetto di non utilizzare il terminale per più di ~ 60 secondi, corro topper assicurarmi che la connessione non si interrompa. (E sono abbastanza sicuro che sia la connessione Comcast poiché stiamo usando solo un router WRT standard e un firewall al lavoro e la mia connessione Comcast domestica non si interrompe mai)
Patrick

Ho aggiunto una breve nota specifica per le connessioni SSH.
David Spillett,

2
Profondità e comprensione in questa risposta. Dovresti ottenere un +3 per questo. Scusa, posso darti solo +1.
RolandoMySQLDBA il

116

INTRODUZIONE AL FARE BACKUP CON mysqldump

IMHO Fare backup è diventato più una forma d'arte se sai solo come affrontarlo

Hai delle opzioni

Opzione 1: mysqldump un'intera istanza mysql

Questo è il più semplice, il gioco da ragazzi !!!

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

Tutto scritto in un unico file: strutture di tabelle, indici, trigger, procedure memorizzate, utenti, password crittografate. Altre opzioni di mysqldump possono anche esportare diversi stili di comandi INSERT, file di registro e coordinate di posizione da registri binari, opzioni di creazione del database, dati parziali (opzione --where) e così via.

Opzione 2: mysqldump database separati in file di dati separati

Inizia creando un elenco di database (2 tecniche per farlo)

Tecnica 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

Tecnica 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

La tecnica 1 è il modo più veloce. La tecnica 2 è la più sicura e sicura. La tecnica 2 è migliore perché, a volte, gli utenti creano cartelle per scopi generali in / var / lib / mysql (datadir) che non sono correlate al database. Information_schema registra la cartella come database nella tabella information_schema.schemata. La tecnica 2 ignorerebbe le cartelle che non contengono dati mysql.

Una volta compilato l'elenco dei database, è possibile procedere a scorrere l'elenco e mysqldump, anche in parallelo, se desiderato.

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

Se ci sono troppi database da avviare contemporaneamente, esegui il dump parallelo di 10 alla volta:

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

Opzione 3: mysqldump tabelle separate in file di dati separati

Inizia creando un elenco di tabelle

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

Quindi scaricare tutte le tabelle in gruppi di 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

Opzione 4: USA LA TUA IMMAGINAZIONE

Prova le varianti delle opzioni sopra menzionate e le tecniche per istantanee pulite

Esempi

  1. Ordinare l'elenco delle tabelle in base alla dimensione di ciascuna tabella crescente o decrescente.
  2. Utilizzando un processo separato, eseguire "FLUSH TABLES WITH READ LOCK; SELECT SLEEP (86400)" prima di avviare mysqldumps. Uccidi questo processo dopo che mysqldumps è completo. Ciò è utile se un database contiene sia InnoDB che MyISAM
  3. Salvare i mysqldumps in cartelle datate e ruotare le vecchie cartelle di backup.
  4. Carica l'intera istanza mysqldumps in server autonomi.

AVVERTIMENTO

Solo l'opzione 1 porta tutto. Lo svantaggio è che mysqldumps creato in questo modo può essere ricaricato solo nella stessa versione di mysql di rilascio di mysqldump generata da mysqldump. In altre parole, un mysqldump da un database MySQL 5.0 non può essere caricato in 5.1 o 5.5. La ragione ? Lo schema mysql è totalmente diverso tra le versioni principali.

Le opzioni 2 e 3 non includono il salvataggio di nomi utente e password.

Ecco il modo generico per scaricare le sovvenzioni SQL per gli utenti che è leggibile e più portatile

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

L'opzione 3 non salva le procedure memorizzate, quindi è possibile effettuare le seguenti operazioni

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

Un altro punto che dovrebbe essere notato riguarda InnoDB. Se si dispone di un pool buffer InnoDB di grandi dimensioni, è consigliabile scaricarlo nel modo migliore prima di eseguire qualsiasi backup. Altrimenti, MySQL passa il tempo a svuotare le tabelle con la pagina sporca rimanente dal pool di buffer. Ecco cosa suggerisco:

Circa 1 ora prima di eseguire il backup eseguire questo comando SQL

SET GLOBAL innodb_max_dirty_pages_pct = 0;

In MySQL 5.5 il valore predefinito innodb_max_dirty_pages_pct è 75. In MySQL 5.1 e versioni precedenti, il valore predefinito innodb_max_dirty_pages_pct è 90. Impostando innodb_max_dirty_pages_pct su 0, questo accelererà il flusso di pagine sporche su disco. Ciò impedirà o almeno ridurrà l'impatto della ripulitura di eventuali commit incompleti a due fasi dei dati InnoDB prima di eseguire qualsiasi mysqldump su qualsiasi tabella InnoDB.

PAROLA FINALE SU mysqldump

Molte persone evitano mysqldump a favore di altri strumenti e questi strumenti sono davvero buoni.

Tali strumenti includono

  1. MAATKIT ( script di dump / ripristino paralleli , da Percona [obsoleto ma eccezionale])
  2. XtraBackup (TopNotch Snapshot Backup da Percona)
  3. CDP R1Soft ( opzione modulo MySQL che acquisisce istantanee temporizzate)
  4. MySQL Enterprise Backup (precedentemente InnoDB Hot Backups [commerciale])

Se hai lo spirito di un vero DBA MySQL, puoi abbracciare mysqldump e avere la padronanza completa su di esso che può essere raggiunta. Possano tutti i tuoi backup riflettere le tue capacità di DBA MySQL .


2
+1 per un buon uso di mysqldump e per: Se hai lo spirito di un vero DBA MySQL, puoi abbracciare mysqldump e avere la completa padronanza su di esso che può essere raggiunta. Possano tutti i tuoi backup essere un riflesso delle tue abilità come DBA MySQL .... Grandi linee !!!
Abdul Manaf,

4
In InnoDB, il dumping delle tabelle singolarmente ti darà un backup incoerente.
Alain Collins,

5
@AlainCollins questo è il motivo per cui eseguo mysqldumps su uno slave di replica di sola lettura. Quando Seconds_Behind_Master è 0, si esegue STOP SLAVE. Ora hai un punto costante nel tempo per fare mysqldumps in uno degli stili di cui sopra. L'ho fatto per le società di trading online negli ultimi 5 anni senza nemmeno una lamentela con me o con i proprietari della mia azienda. A partire da questo momento, eseguo mysqldumps paralleli ogni 10 minuti per questo client. Faccio anche questo per altri client per fornire periodi di backup più rapidi.
RolandoMySQLDBA il

Ho un db da 32 GB, quindi l'opzione 3 è esattamente quello che avevo in mente! Grazie!
Raymond,

Devo eseguire il backup e reimportare 1 TB di dati per ridurli estremamente grandi ibdata1. In tempi di SSD supportati da RAID hardware, l'opzione 3 è l'unica soluzione per me.
rabudde,

18

Dai un'occhiata al master di replica MySQL su slave. Consente di clonare il database del master su un altro server di database con lo stesso database. Ciò include le identità master e slave. Slave si rende la copia esatta del server di database principale e / o dei suoi database. Potrebbe esserci una relazione uno-uno-molti-molti-uno tra il / i maestro / i e il / i schiavo / i.

Lo slave legge continuamente il registro binario sul master (il registro bin memorizza le query scritte sul server del database master) e ottiene l'input sul suo server del database slave. (questo significa che il tuo database principale non sarà affatto interessato)

La buona notizia è che non influenzerà troppo il tuo server MySQL in quanto non noterai tempi di inattività o risposte lente alle query. Lo usiamo per database da 10 Gb e funziona come un incantesimo senza tempi di inattività.

Replica di MySQL sulla stessa macchina


mentre quello funzionerebbe per me, penso che potrebbe essere un po 'eccessivo. Al momento non ho bisogno di quel livello di backup, anche se lo terrò presente nel caso in cui i requisiti dell'applicazione cambiassero.
Patrick

4
+1 per il backup di una replica per rimuovere il carico I / O del backup dal DB principale e ridurre potenziali problemi relativi al blocco, con un avvertimento significativo: fare attenzione con l'opzione "replica sulla stessa macchina" delle operazioni sullo slave può competere con il master per la larghezza di banda IO - assicurarsi che i file di dati dello slave siano un drive / array diverso rispetto al master per mitigare questo problema.
David Spillett,

1
Idem sul commento di David Splllet. Configuro e mantengo dozzine di Master / Slaves con backup mysqldump sugli slave per My Web Hosting Employer. +1 anche da me.
RolandoMySQLDBA il

16

Piano A: vedi anche Xtrabackup da Percona. Ciò consente il backup online di InnoDB, senza alcun blocco significativo.

Piano B: uno slave può essere arrestato e puoi eseguire un backup coerente con uno dei diversi modi (copia file, mysqldump, xtrabackup, ecc.)

Piano C: Istantanea LVM. Dopo alcune impostazioni criptiche, i tempi di inattività di un backup sono inferiori a un minuto, indipendentemente dalle dimensioni del database. Interrompi mysqld, esegui l'istantanea, riavvia mysqld, quindi copia l'istantanea. L'ultimo passaggio può richiedere molto tempo, ma MySQL non è inattivo.

Piano D: Istantanea di uno Slave - zero tempi di inattività.


2
Hoorah a tutti e quattro i piani. Posso solo dare +0.25 per risposta !!! +1 (4 x 0,25)
RolandoMySQLDBA

15

Prima alcuni punti di amministrazione: ti stai connettendo per fare un ftp o sei entrato e sta morendo? Se ssh, assicurati di usare lo schermo in modo da poter riprendere dopo l'incidente di Comcast. Se ftp, assicurati di comprimerlo / tar prima dell'invio.

Prova anche il parametro --opt o --quick

--opt Questa opzione attiva una serie di opzioni aggiuntive per rendere più efficienti le operazioni di dump e ricarica. In particolare, equivale a usare insieme le opzioni --add-drop-table, --add-locks, --all, --quick, --extended-insert, --lock-tables e --disable-keys. Si noti che questa opzione rende l'output meno portatile e meno comprensibile per altri sistemi di database.

--quick Questa opzione dice a mysqldump di scrivere l'output di dump mentre legge ogni riga dal server, il che potrebbe essere utile per le tabelle di grandi dimensioni. Per impostazione predefinita, mysqldump legge tutte le righe da una tabella in memoria prima di scrivere l'output; per tabelle di grandi dimensioni, ciò richiede grandi quantità di memoria, che potrebbe causare il fallimento del dump.


1
--Opt non aumenterà la dimensione del file che alla fine otterrà l'output?
Toby,

Aggiungerà un po '- volevo aggiungere --quick, che è più in risposta al suo problema .... modifica ora. Grazie!
David Hall,

+1 per lo schermo, che evita del tutto questo problema
Gaius

+1 per una risposta molto bella e concisa per le spiegazioni --opt e --quick di mysqldump.
RolandoMySQLDBA,

1
--opt è attivo per impostazione predefinita.
Giordania,

5

Avevo problemi con i timeout anche durante il dump di grandi database. Ho finalmente risolto se inviando singoli comandi per ogni tabella nel db e aggiungendo tutto a un file come questo:

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
Questo è considerato un backup "incoerente", in quanto al momento del ripristino è possibile che in una tabella siano presenti dati mappati a un'altra ma che non esiste.
Morgan Tocker,

3

Penso che la domanda sia su come ripristinare più velocemente dai file di dump creati da mysqldump, non una diversa soluzione di backup.

Uno dei modi, è possibile farlo, creando gruppi di tabelle nel proprio schema e creando un utente DB separato per ciascun gruppo, quindi infine utilizzare le autorizzazioni MySQL per non consentire l'inserimento delle tabelle nell'uso di tutti gli utenti DB tranne uno.

Questa è una tecnica collaudata, veloce, quasi parallela ma non sicura al 100%, quanto tempo ci vorrà per ripristinare da grandi discariche come 500 G o giù di lì. Ma a mio modesto parere, hai bisogno di qualcosa di parallelo. Controlla il link qui sotto per un esempio.

[Ripristino rapido e parallelo dai dump SQL (mysqldump) per MySQL] [1]

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

"Ripristino rapido e parallelo dai dump SQL (mysqldump) per MySQL"


2
Questa è una copia esatta della tua risposta a un'altra domanda. Potresti volerlo personalizzare un po 'di più per questa domanda specifica.
Paul White

La domanda NON riguarda in particolare come ripristinare più velocemente.
Andrew Lorien,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.