Como otimizar um mysqldump de um banco de dados grande?


173

Eu tenho um aplicativo symfony com um banco de dados InnoDB que é ~ 2GB com 57 tabelas. A maioria do tamanho do banco de dados reside em uma única tabela (~ 1,2 GB). Atualmente, estou usando o mysqldump para fazer backup do banco de dados todas as noites.

Devido à minha conexão comcast, muitas vezes, se eu estiver executando um despejo manualmente, minha conexão com o servidor atingirá o tempo limite antes que o despejo seja concluído, fazendo com que eu precise executar novamente o despejo. [Atualmente, eu executo um cron que executa o despejo todas as noites, isto é apenas para despejos executados manualmente.]

Existe uma maneira de acelerar os despejos para o problema de tempo limite da conexão, mas também para limitar o tempo que o servidor está ocupado com esse processo?

BTW, atualmente estou trabalhando para reduzir o tamanho do banco de dados geral para resolver esse problema.


2
Quais parâmetros (se houver) você está passando para o comando mysqldump?
Toby

Adicionar --compact pode ser uma opção para você.
Toby

nada realmente -mysqldump [database] -u[user] -p'[password]' > db_backup.sql
Patrick

4
Uma alternativa simples para screena sua situação seria usar nohup, ele permitirá que seu comando continue em execução no servidor, mesmo se sua conexão cair. Por exemplo nohup mysqldump [options] > backup.sql 2> backup.err &. Se você não fornecer um arquivo de saída nohup, ele será criado nohup.outpor padrão.
dabest1

1
Dê uma olhada ate screen(o último se instalado, mas até padrão em todos os unixes) ou as ServerAliveIntervalopções do SSH para formas de lidar com o firewall que o interrompe após uma conexão inativa por muito tempo.
Matt Bianco

Respostas:


134

O principal gargalo no dump como esse é a unidade de E / S. Você está lendo uma carga de dados e os escrevendo novamente. Você pode acelerar isso de várias maneiras:

  • Verifique se a saída está indo para uma (s) unidade (s) diferente daquela (s) em que os arquivos do banco de dados estão armazenados - isso fará uma enorme diferença com os discos giratórios, pois os cabeçotes das unidades não estarão constantemente alternando entre o local que está sendo lido. e o local que está sendo gravado.
  • A saída do mysqldump será muito compressível, portanto, se você não puder separar a saída da entrada, como mencionado acima, canalize a saída gzipou similar. Isso reduzirá a quantidade de gravações que estão sendo feitas (reduza a carga geral de E / S e a quantidade de movimento da cabeça) às custas de algum tempo da CPU (que você pode ter muito de sobra nesses momentos).
  • Além disso, (como ou em vez de compactação) passa a saída por um utilitário de pipe (como pv ) que suporta grandes buffers de gravação para agrupar blocos gravados nas unidades mais uma vez, novamente para reduzir o efeito da latência do movimento da cabeça - isso fará com que bastante diferente se estiver usando a --quickopção para reduzir o impacto da RAM de fazer backup de tabelas grandes).
  • Execute seu processo de backup apenas quando a carga de E / S estiver baixa.

Você pode estar corrigindo o problema errado: pode ser mais fácil resolver as quedas de conexão (embora reduzir a carga de E / S imposta por seus backups ajude a reduzir o efeito que você tem sobre outros usuários, vale a pena tentar de qualquer maneira). Você poderia executar seus backups manuais através da tela (ou ferramentas similares como o tmux )? Dessa forma, se sua conexão com o servidor cair, você pode simplesmente reconectar e reconectar à screensessão sem que nenhum processo seja interrompido.

Se você estiver enviando os dados diretamente pela conexão (ou seja, você estiver executando o mysqldump em sua máquina local em um banco de dados remoto, para que o dump apareça localmente), é melhor executar o dump no servidor primeiro, compactando conforme necessário e transferindo os dados pela rede usando uma ferramenta (como rsync) que suporta transferências parciais, para que você possa retomar a transferência (em vez de reiniciar) se uma queda de conexão a interromper.

Como parte de sua "redução do tamanho do banco de dados geral para resolver esse problema", eu acho que uma grande parte dos seus dados não muda. Você pode mover uma grande parte dos 1,2 Gb dessa tabela principal para outra e removê-la daqueles que são copiados pela mysqldumpchamada. Você não precisa fazer backup desses dados sempre que eles nunca mudarem. A divisão de dados entre tabelas e bancos de dados dessa maneira geralmente é chamada de particionamento de dados e também pode permitir que você distribua os dados e a carga de E / S em várias unidades. O banco de dados topo de linha possui suporte embutido para particionamento automático, embora no mysql você provavelmente precise fazer isso manualmente e alterar sua camada de acesso a dados para justificá-lo.

Desviando do tópico para este site (você provavelmente deve passar para o ServerFault ou SuperUser para perguntar se precisa de mais detalhes): Se você parece estar perdendo conexões devido à inatividade, verifique as opções no servidor SSH e no cliente SSH para fazer Verifique se os pacotes keep-alive estão ativados e sendo enviados com frequência suficiente. Se houver queda mesmo que a conexão esteja ativa, você também pode tentar usar o OpenVPN ou similar para quebrar a conexão - ela deve lidar com uma queda curta e até completa se toda a conexão ficar inativa por alguns segundos, de modo que o cliente SSH e servidor não percebe.


Eu gostaria de poder reduzir o número de conexões ssh descartadas para meus servidores. Se espero não usar o terminal por mais de ~ 60 segundos, corro toppara garantir que a conexão não caia. (E eu tenho certeza que é a conexão Comcast já que só está usando um roteador WRT Standard & firewall no trabalho e minha conexão casa Comcast nunca cai)
Patrick

Adicionei uma breve nota específica às conexões SSH.
David Spillett

2
Profundidade e insight nesta resposta. Você deve obter um +3 para isso. Desculpe, só posso lhe dar +1.
RolandoMySQLDBA 23/06

116

INSIGHT PARA FAZER BACKUP COM O mysqldump

IMHO Fazer backups tornou-se mais uma forma de arte se você souber exatamente como abordá-la

Você tem opções

Opção 1: mysqldump uma instância inteira do mysql

Este é o mais fácil, o acéfalo !!!

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

Tudo escrito em um arquivo: estruturas de tabela, índices, gatilhos, procedimentos armazenados, usuários, senhas criptografadas. Outras opções do mysqldump também podem exportar diferentes estilos de comandos INSERT, arquivo de log e coordenadas de posição de logs binários, opções de criação de banco de dados, dados parciais (opção --where) e assim por diante.

Opção 2: mysqldump separa bancos de dados em arquivos de dados separados

Comece criando uma lista de bancos de dados (2 técnicas para fazer isso)

Técnica 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

Técnica 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

A técnica 1 é a maneira mais rápida. A técnica 2 é a mais segura e segura. A técnica 2 é melhor porque, às vezes, os usuários criam pastas para fins gerais em / var / lib / mysql (datadir) que não são relacionados ao banco de dados. O information_schema registraria a pasta como um banco de dados na tabela information_schema.schemata. A técnica 2 ignoraria pastas que não contêm dados mysql.

Depois de compilar a lista de bancos de dados, você pode avançar pela lista e mysqldump, mesmo em paralelo, se assim o desejar.

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

Se houver muitos bancos de dados a serem iniciados ao mesmo tempo, despeje-os paralelamente 10 por vez:

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

Opção 3: mysqldump separa tabelas em arquivos de dados separados

Comece criando uma lista de tabelas

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

Em seguida, despeje todas as tabelas em grupos de 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

Opção 4: USE SUA IMAGINAÇÃO

Experimente variações das opções acima mencionadas e técnicas para capturas instantâneas limpas

Exemplos

  1. Ordene a lista de tabelas pelo tamanho de cada tabela, ascendente ou descendente.
  2. Usando um processo separado, execute "FLUSH TABLES WITH READ LOCK; SELECT SLEEP (86400)" antes de iniciar o mysqldumps. Mate esse processo após a conclusão do mysqldumps. Isso é útil se um banco de dados contiver InnoDB e MyISAM
  3. Salve o mysqldumps em pastas datadas e gire as pastas de backup antigas.
  4. Carregue o mysqldumps de instância inteira em servidores independentes.

EMBARGO

Somente a opção 1 traz tudo. A desvantagem é que o mysqldumps criado dessa maneira só pode ser recarregado na mesma versão principal do mysql que o mysqldump foi gerado. Em outras palavras, um mysqldump de um banco de dados MySQL 5.0 não pode ser carregado em 5.1 ou 5.5. O motivo ? O esquema do mysql é totalmente diferente entre os principais lançamentos.

As opções 2 e 3 não incluem salvar nomes de usuário e senhas.

Aqui está a maneira genérica de despejar o SQL Grants para usuários que sejam legíveis e mais portáteis

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

A opção 3 não salva os procedimentos armazenados, portanto, você pode fazer o seguinte

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

Outro ponto que deve ser observado é o InnoDB. Se você possui um buffer pool grande do InnoDB, faz sentido liberá-lo da melhor forma possível antes de executar qualquer backup. Caso contrário, o MySQL gasta o tempo limpando tabelas com as sobras de páginas sujas do buffer pool. Aqui está o que eu sugiro:

Cerca de 1 hora antes de executar o backup, execute este comando SQL

SET GLOBAL innodb_max_dirty_pages_pct = 0;

No MySQL 5.5, o padrão innodb_max_dirty_pages_pct é 75. No MySQL 5.1 e vice-versa, o innodb_max_dirty_pages_pct é 90. Ao definir innodb_max_dirty_pages_pct como 0, isso acelera a liberação de páginas sujas para o disco. Isso impedirá ou pelo menos diminuirá o impacto da limpeza de confirmações bifásicas incompletas dos dados do InnoDB antes de executar qualquer mysqldump em qualquer tabela do InnoDB.

PALAVRA FINAL NO mysqldump

A maioria das pessoas evita o mysqldump em favor de outras ferramentas e essas ferramentas são realmente boas.

Tais ferramentas incluem

  1. MAATKIT ( scripts de despejo / restauração paralelos , da Percona [obsoleto, mas ótimo])
  2. XtraBackup (backup de instantâneo TopNotch da Percona)
  3. CDP R1Soft ( opção do módulo MySQL que tira instantâneos point-in-time)
  4. MySQL Enterprise Backup (anteriormente InnoDB Hot Backups [comercial])

Se você tem o espírito de um verdadeiro DBA do MySQL, pode abraçar o mysqldump e ter o domínio completo sobre ele que pode ser alcançado. Que todos os seus backups sejam um reflexo de suas habilidades como um DBA do MySQL .


2
+1 para um bom uso do mysqldump e também: Se você tem o espírito de um verdadeiro DBA do MySQL, pode abraçar o mysqldump e ter o domínio completo sobre isso que pode ser alcançado. Que todos os seus backups sejam um reflexo de suas habilidades como um DBA MySQL .... Ótimas linhas !!!
Abdul Manaf

4
No InnoDB, despejar tabelas individualmente fornecerá um backup inconsistente.
Alain Collins

5
@AlainCollins é por isso que eu executo o mysqldumps em um escravo de replicação que é somente leitura. Depois que Seconds_Behind_Master for 0, você executa o STOP SLAVE. Agora você tem um ponto consistente no tempo para executar o mysqldumps em qualquer um dos estilos mencionados acima. Eu fiz isso para empresas de comércio on-line nos últimos 5 anos sem uma única reclamação para mim ou para os proprietários da minha empresa. A partir deste momento, eu faço o mysqldumps paralelo a cada 10 minutos para este cliente. Também faço isso para outros clientes para fornecer períodos de backup mais rápidos.
RolandoMySQLDBA

Eu tenho um db de 32GB, então a opção 3 é exatamente o que eu tinha em mente! obrigado!
Raymond

Eu tenho que fazer backup e reimportar 1 TB de dados para encolher extremamente grande ibdata1. Em tempos de SSDs suportados por hardware RAID, a opção 3 é a única solução para mim.
rabudde 18/02/19

18

Dê uma olhada no mestre de replicação do MySQL para escravo. Ele permite clonar o banco de dados do mestre para outro servidor de banco de dados com o mesmo banco de dados. Isso inclui as identidades de mestre e escravo. O Slave faz a cópia exata do servidor de banco de dados mestre e / ou de seus bancos de dados. Pode haver uma relação um-um-muitos-muitos-um entre mestre (s) e escravo (s).

O escravo lê continuamente o log binário no mestre (o log do bin armazena as consultas gravadas no servidor de banco de dados mestre) e obtém entrada para o servidor de banco de dados escravo. (isso significa que seu banco de dados mestre não será afetado)

A boa notícia é que isso não afetará muito o servidor MySQL, pois você não notará tempos de inatividade ou respostas lentas de consulta. Usamos para bancos de dados de 10Gb e funciona como um encanto, sem nenhum tempo de inatividade.

Replicação MySQL na mesma máquina


Embora isso funcione para mim, acho que pode ser um pouco exagerado. Atualmente, não preciso desse nível de backup, embora tenha isso em mente caso os requisitos do aplicativo sejam alterados.
Patrick

4
+1 para fazer backup de uma réplica para remover a carga de E / S do backup do banco de dados principal e reduzir possíveis problemas relacionados ao bloqueio, com uma ressalva significativa: tenha cuidado com a opção "réplica na mesma máquina" que suas operações no escravo pode competir com o mestre pela largura de banda de E / S - verifique se os arquivos de dados do escravo são uma unidade / matriz diferente do mestre para minimizar esse problema.
precisa saber é o seguinte

1
O mesmo vale para o comentário de David Splllet. Eu configuro e mantenho dezenas de Master / Slaves com backups mysqldump nos escravos para o My Web Hosting Employer. +1 de mim também.
RolandoMySQLDBA

16

Plano A: Veja também o Xtrabackup da Percona. Isso permite backup online do InnoDB, sem nenhum bloqueio significativo.

Plano B: Um escravo pode ser interrompido e você pode fazer um backup consistente por qualquer um dos vários meios (copiar arquivos, mysqldump, xtrabackup, etc.)

Plano C: Instantâneo LVM. Após alguma configuração enigmática, o tempo de inatividade para um backup é inferior a um minuto, independentemente do tamanho do banco de dados. Você para o mysqld, faz o instantâneo, reinicia o mysqld e copia o instantâneo. O último passo pode demorar, mas o MySQL não está inativo.

Plano D: Instantâneo de um escravo - tempo de inatividade zero.


2
Hoorah para todos os quatro planos. Só posso dar +0,25 por resposta !!! 1 (4 x 0,25)
RolandoMySQLDBA

15

Alguns pontos de administração primeiro: você está se conectando para fazer um ftp ou está conectado e ele está morrendo? Se ssh, certifique-se de usar a tela para que você possa retomar após a falha do comcast. Se for ftp, verifique se você está compactando / tar antes do envio.

Experimente também o parâmetro --opt ou --quick

--opt Esta opção ativa um conjunto de opções adicionais para tornar as operações de despejo e recarregamento mais eficientes. Especificamente, é equivalente a usar as opções --add-drop-table, --add-locks, --all, --quick, --extended-insert, --lock-tables e --disable-keys juntas. Observe que essa opção torna a saída menos portátil e menos provável de ser entendida por outros sistemas de banco de dados.

--quick Esta opção diz ao mysqldump para escrever a saída de despejo enquanto lê cada linha do servidor, o que pode ser útil para tabelas grandes. Por padrão, o mysqldump lê todas as linhas de uma tabela na memória antes de escrever a saída; para tabelas grandes, isso requer grandes quantidades de memória, possivelmente causando falha no dump.


1
--Opt não aumentará o tamanho do arquivo que obterá a saída?
Toby

Ele irá adicionar alguns - eu quis acrescentar - quick, o que é mais uma resposta ao seu problema .... editando agora. Obrigado!
David Hall

+1 para tela, o que evita esse problema por completo
Gaius

+1 para uma resposta muito agradável e concisa para as explicações --opt e --quick do mysqldump.
RolandoMySQLDBA

1
--opt está ativado por padrão.
Jordan

5

Eu costumava ter problemas com tempos limite durante despejos de grandes bancos de dados também. Finalmente resolvi se enviando comandos individuais para todas as tabelas no banco de dados e anexando tudo a um arquivo como este:

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
Isso é considerado um backup "inconsistente", pois na restauração você pode ter dados em uma tabela que mapeia para outra, mas não existe.
Morgan Tocker

3

Eu acho que a pergunta é sobre como restaurar mais rapidamente dos arquivos de despejo criados pelo mysqldump, não uma solução de backup diferente.

Uma das maneiras de fazer isso é criando grupos de tabelas em seu esquema e crie um usuário de banco de dados separado para cada grupo e, finalmente, use as permissões do MySQL para não permitir que tabelas sejam inseridas usando apenas um usuário de banco de dados.

Essa é uma técnica comprovada, rápida e quase paralela, mas sem 100% de certeza, quanto tempo levará para restaurar a partir de lixões grandes como 500G ou mais. Mas, na minha humilde opinião, você precisa de algo paralelo. Confira o link abaixo para ver um exemplo.

[Restauração rápida e paralela de dumps SQL (mysqldump) para MySQL] [1]

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

"Restauração rápida e paralela de dumps SQL (mysqldump) para MySQL"


2
Esta é uma cópia exata da sua resposta para outra pergunta. Convém personalizá-lo um pouco mais para esta pergunta específica.
Paul White

A questão NÃO é especificamente sobre como restaurar mais rapidamente.
andrew lorien
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.