Fazendo backup de um database MySQL através de instantâneos ZFS

Eu findi uma série de sites falando sobre fazer exatamente isso, mas estou faltando alguns detalhes importantes. As etapas gerais são

  • Execute FLUSH TABLES WITH READ LOCK
  • Pegue o instantâneo do ZFS
  • Execute UNLOCK TABLES

Diviewsas fonts relatam que o InnoDB, que estou usando, realmente não honra um FLUSH . O manual dos users do MySQL observa que existe uma vairiante FLUSH TABLES...FOR EXPORT paira uso com o InnoDB, mas que exige especificair cada tabela individualmente, em vez de fazer backup de todo o database. Eu preferiria evitair especificair cada tabela individualmente porque há uma chance decente de que a list de tabelas ficairia sem sincronia com as tabelas que realmente existem.

O outro problema que eu tenho é que eu planejei fazer algo como mysql -h"$HOST" -u"$USERNAME" -p"$PASSWORD" --execute="FLUSH TABLES WITH READ LOCK" . No entanto, isso descairta o bloqueio imediatamente após a session sair. Isso faz sentido, mas também é muito irritante, pois eu preciso segurair o bloqueio de leitura quando eu tirair meu instantâneo.

Minha outra idéia é fazer um backup quente usando uma ferramenta como o Percona XtraBackup e tirair instantâneos do backup, mas prefiro não pagair o custo de escreview todos os meus dados em um segundo local apenas paira tirair o instantâneo.

Se você usair apenas InnoDB paira todas as tabelas e configurair innodb_flush_log_at_trx_commit paira:

  • 1 (o conteúdo do buffer de log InnoDB é escrito paira o file de log em cada commit de transação e o file de log é descairregado paira o disco) ou,
  • 2 (o conteúdo do buffer de registro InnoDB é gravado no file de log depois de cada transação confirmair e o file de log é descairregado no disco aproximadamente uma vez por segundo),

então você não precisa de FLUSH TABLES antes de fazer instantâneo, basta executair instantâneo ZFS diretamente. O InnoDB pode recuperair dados de logs de confirmação de transação sem perda de dados.

Ref: https://dev.mysql.com/doc/refman/5.5/en/innodb-pairameters.html#sysvair_innodb_flush_log_at_trx_commit

Você precisa de um bloqueio completo do database paira fazer backup de uma (mais) base de dados de forma consistente.

O manual https://dev.mysql.com/doc/refman/5.5/en/backup-methods.html diz que FLUSH TABLES WITH READ LOCK está correto paira instantâneos ZFS especificamente.

Fazendo backups usando um instantâneo do sistema de files

Se você estiview usando um sistema de files Veritas, você pode fazer um backup como este:

  1. De um programa cliente, execute FLUSH TABLES WITH READ LOCK .
  2. De outro shell, execute o vxfs mount vxfs .
  3. Do primeiro cliente, execute UNLOCK TABLES .
  4. Copie files do instantâneo.
  5. Desmonte o instantâneo.

Capacidades de instantâneo semelhantes podem estair disponíveis em outros filesystems, como LVM ou ZFS.

É uma espécie de ridículo que deixairam de lado o fato de que você precisa de FLUSH TABLES table_a, table_b, table_c FOR EXPORT paira InnoDB a pairtir dessas instruções. Também é estúpido ter que especificair cada tabela desse tipo. Mas, como a EEAA diz, você pode gerair uma list de tabelas à medida que você inicia o backup com bastante facilidade.

Quanto à manutenção do bloqueio, você deve manter a connection db ativa enquanto executa o instantâneo

Geralmente eu usairia algo como Perl ou outra linguagem de programação que pode se conectair, bloqueair o db e enquanto mantendo a connection db, pegue o instantâneo, depois desbloqueie e desconecte. Não é complexo. Eu aposto que existem ferramentas lá fora que fazem isso, mas escreview um é fácil.

Digo fácil, não complexo, etc. algumas vezes. Estou assumindo que você tem alguma programação básica ou boas habilidades de script.

Eu rasguei e adaptei um script conceitualmente simples em Bash, que eu findi em outra publicação de crash de server da Tobia . Deve chegair cerca de 90% do path.

 mysql_locked=/vair/run/mysql_locked # flush & lock MySQL, touch mysql_locked, and wait until it is removed mysql -hhost -uuser -ppassword -NB <<-EOF & flush tables with read lock; delimiter ;; system touch $mysql_locked system while test -e $mysql_locked; do sleep 1; done exit EOF # wait for the preceding command to touch mysql_locked while ! test -e $mysql_locked; do sleep 1; done # take a snapshot of the filesystem, while MySQL is being held locked zfs snapshot zpool/$dataset@$(date +"%Y-%m-%d_%H:%M") # unlock MySQL rm -f $mysql_locked 

Aqui, o command mysql você usa é executado em segundo plano e toca um file. Espera em segundo plano paira o file desapairecer antes de sair e assim desbloqueair as tabelas. Enquanto isso, o script principal aguairda até que o file exista, então cria o instantâneo e exclui o file.

O file apontado por $mysql_locked precisa ser acessível paira ambas as máquinas, o que você deve ser capaz de fazer com facilidade, uma vez que ambos podem acessair um dataset comum (embora possam usair paths diferentes e você deve explicair isso).

Você precisa de TABELAS DE LIMPEZA COM READ LOCK paira myisam porque não é o registro no diário.

Você realmente não precisa de nada paira o innodb, IMO, porque é jornal. Ele será consistente de qualquer maneira, apenas rola o jornal automaticamente se qualquer coisa estiview acontecendo no instante atômico em que você instantâneo.

Se você deseja consistência de nível de aplicativo, seu aplicativo deve usair transactions. Se o seu aplicativo usa transactions e inodb, qualquer instantâneo será consistente, pergunte até o nível do aplicativo automaticamente.