Atualização do MySQL (Percona Server) de 5.7 para 8.0

Atualização do MySQL (Percona Server) de 5.7 para 8.0

O progresso não para, por isso, as razões para atualizar para versões atuais do MySQL se tornam cada vez mais significativas. Recentemente, em um de nossos projetos, chegou a hora de atualizar os confortáveis clusters do Percona Server 5.7 para a versão 8. Isso aconteceu na plataforma Ubuntu Linux 16.04. Como realizar tal operação com o mínimo de inatividade e quais problemas encontramos durante a atualização — leia neste artigo.

Preparação

Qualquer atualização de servidor de banco de dados provavelmente está relacionada à reconfiguração do banco: mudanças nas exigências de limites dos recursos do sistema e na correção das configurações do banco, que precisam ser limpas de diretivas obsoletas.

Antes da atualização, devemos consultar a documentação oficial:

E elaborar um plano de ação:

  1. Corrigir os arquivos de configuração, removendo as diretivas obsoletas.
  2. Verificar a compatibilidade com ferramentas.
  3. Atualizar as bases de dados slave, instalando o pacote percona-server-server.
  4. Atualizar o mestre, instalando o mesmo pacote.

Vamos revisar cada item do plano e ver o que pode dar errado.

IMPORTANTE! O procedimento de atualização do cluster MySQL baseado em Galera tem suas particularidades, que não estão descritas neste artigo. Não utilize este guia nesse caso.

Parte 1: Verificação das configurações

Na versão 8 do MySQL, foi removido query_cache. Na verdade, ele foi considerado obsoleto já na versão 5.7, mas agora foi removido completamente. Portanto, é necessário remover as diretivas relacionadas. Para o cache de consultas, agora podem ser utilizados ferramentas externas — por exemplo, ProxySQL.

Além disso, no arquivo de configuração foram encontradas diretivas obsoletas sobre innodb_file_format. Se na versão 5.7 do MySQL havia a possibilidade de escolha do formato InnoDB, a versão 8 já funciona somente com o formato Barracuda.

Nosso resultado — remoção das seguintes diretivas:

  • query_cache_type, query_cache_limit e query_cache_size;
  • innodb_file_format e innodb_file_format_max.

Para a verificação, utilizaremos a imagem Docker do Percona Server. O arquivo de configuração do servidor será colocado no diretório mysql_config_test, e ao lado, criaremos diretórios para dados e logs. Exemplo de teste da configuração do percona-server:

mkdir -p {mysql_config_test,mysql_data,mysql_logs}
cp -r /etc/mysql/conf.d/* mysql_config_test/
docker run --name some-percona -v $(pwd)/mysql_config_test:/etc/my.cnf.d/ -v $(pwd)/mysql_data/:/var/lib/mysql/ -v $(pwd)/mysql_logs/:/var/log/mysql/ -e MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD} -d percona:8-centos

Conclusão: haverá um arquivo nos logs do Docker ou no diretório de logs — dependendo das suas configurações — que descreverá as diretivas problemáticas.

Isso é o que encontramos:

2020-04-03T12:44:19.670831Z 0 [Warning] [MY-011068] [Server] A sintaxe 'expire-logs-days' está obsoleta e será removida em uma versão futura. Por favor, use binlog_expire_logs_seconds em vez disso.
2020-04-03T12:44:19.671678Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' é atualmente um alias para o conjunto de caracteres UTF8MB3, mas será um alias para UTF8MB4 em uma versão futura. Por favor, considere usar UTF8MB4 para ser inequívoco.
2020-04-03T12:44:19.671682Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' é uma colação do conjunto de caracteres obsoleto UTF8MB3. Por favor, considere usar UTF8MB4 com uma colação apropriada em vez disso.

Assim, precisamos também resolver as codificações e substituir a diretiva obsoleta expire-logs-days.

Parte 2: Verificando instalações em funcionamento

Na documentação de atualização, existem 2 utilitários para verificar a compatibilidade do banco de dados. O uso deles ajuda o administrador a verificar a compatibilidade da estrutura de dados existente.

Vamos começar com a utilidade clássica mysqlcheck. Basta executá-la:

mysqlcheck -u root -p --all-databases --check-upgrade

Se nenhum problema for encontrado, a utilidade terminará com o código 0:

Atualização do MySQL (Percona Server) de 5.7 para 8.0

Além disso, nas versões modernas do MySQL, está disponível a utilidade mysql-shell (no caso do Percona, é o pacote percona-mysql-shell). Ela substitui o cliente clássico mysql e combina funções de cliente, editor de código SQL e ferramentas de administração do MySQL. Para verificar o servidor antes da atualização, você pode executar o seguinte comando através dela:

mysqlsh -- util check-for-server-upgrade { --user=root --host=1.1.1.1 --port=3306 } --config-path=\/etc\/mysql\/my.cnf

E aqui estão as observações que recebemos:

Atualização do MySQL (Percona Server) de 5.7 para 8.0

No geral, nada crítico — apenas avisos sobre codificações. (veja abaixo)O resultado geral da execução:

Atualização do MySQL (Percona Server) de 5.7 para 8.0

Decidimos que a atualização deve ocorrer sem problemas.

Observação sobre os avisos acima, que indicam problemas com codificações. O fato é que o UTF-8 no MySQL, até recentemente, não era o "verdadeiro" UTF-8,pois armazenava apenas 3 bytes em vez de 4. No MySQL 8, finalmente decidimos corrigir isso:o alias utf8 em breve levará à codificação utf8mb4,e as antigas colunas nas tabelas se tornarão utf8mb3.No futuro, a codificação utf8mb3. será removida, mas não nesta versão. Portanto, decidimos corrigir as codificações já na instalação do SGBD em funcionamento, após sua atualização.

Parte 3: Atualizando servidores

O que pode dar errado quando há um plano tão incrível?.. Compreendendo bem que detalhes sempre acontecem, realizamos o primeiro experimento no cluster de desenvolvimento MySQL.

Como já mencionado, a documentação oficial aborda a questão da atualização de servidores MySQL com réplicas. A essência é que primeiro deve-se atualizar todas as réplicas (slave), pois o MySQL 8 consegue replicar a partir de um master da versão 5.7. Uma certa complexidade se deve ao fato de que estamos utilizando o modo master master, onde o master remoto está em modo read-only. Ou seja, o tráfego de produção flui para um data center, enquanto o segundo é o de backup.

A topologia é a seguinte:

Atualização do MySQL (Percona Server) de 5.7 para 8.0

A atualização deve começar pelas réplicas mysql replica dc 2, mysql master dc 2 e mysql replica dc 1, e terminar no servidor mysql master dc 1. Para maior confiabilidade, desligamos as máquinas virtuais, fizemos snapshots e, pouco antes da atualização, interrompemos a replicação com o comando STOP SLAVE. De resto, a atualização parece assim:

  1. Reiniciamos cada réplica, adicionando nas configurações 3 opções: skip-networking, skip-slave-start, skip-log-bin. O fato é que a atualização do banco gera logs binários com a atualização das tabelas de sistema. Essas diretrizes garantem que não haverá alteração dos dados da aplicação no banco e que a informação sobre a atualização das tabelas de sistema não será registrada nos logs binários. Isso evitará problemas na retomada da replicação.
  2. Instalamos o pacote percona-server-server. É importante notar que na versão MySQL 8 não é necessário executar o comando mysqlupgrade após a atualização do servidor.
  3. Após o início bem-sucedido, reinicializamos o servidor novamente — já sem os parâmetros que foram adicionados no primeiro ponto.
  4. Verificamos se a replicação está operando com sucesso: checamos SHOW SLAVE STATUS e observamos que as tabelas com os contadores no banco da aplicação estão sendo atualizadas.

Tudo isso parece bastante simples: a atualização do dev foi bem-sucedida. Ok, podemos planejar a atualização noturna para a produção.

Não houve tristeza — nós atualizamos o prod

No entanto, transferir a experiência bem-sucedida do dev para a produção não ocorreu sem surpresas.

Felizmente, o próprio processo de atualização começa com as réplicas, portanto, ao encontrar dificuldades, interrompemos os trabalhos e restauramos a réplica a partir do snapshot. A investigação dos problemas foi transferida para a manhã seguinte. Nos logs, encontramos as seguintes entradas:

2020-01-14T21:43:21.500563Z 2 [ERROR] [MY-012069] [InnoDB] A tabela: t1 tem 19 colunas, mas o dicionário do InnoDB tem 20 colunas
2020-01-14T21:43:21.500722Z 2 [ERROR] [MY-010767] [Server] Erro ao corrigir os dados SE para db1.t1
2020-01-14T21:43:24.208365Z 0 [ERROR] [MY-010022] [Server] Falha ao popular tabelas DD.
2020-01-14T21:43:24.208658Z 0 [ERROR] [MY-010119] [Server] Abortando

A pesquisa nos arquivos de várias listas de distribuição no Google levou à compreensão de que este problema surge devido a um bug do MySQL. Embora, na verdade, seja até um bug das ferramentas mysqlcheck e mysqlsh.

Descobriu-se que no MySQL mudaram a forma de representação dos dados para campos decimais (int, tinyint etc.), portanto, dentro do mysql-server, utiliza-se uma forma diferente de armazenamento. Se o seu banco de dados originalmente era na versão 5.5 ou 5.1 e depois você atualizou para a 5.7, pode ser necessário realizar OPTIMIZE para algumas tabelas. Então, o MySQL atualizará os arquivos com os dados, convertendo-os para o formato de armazenamento atual.

Isso também pode ser verificado com a ferramenta mysqlfrm:

mysqlfrm --diagnostic -vv /var/lib/mysql/db/table.frm
...
 'field_length': 8,
  'field_type': 246, # formato do campo
  'field_type_name': 'decimal',
  'flags': 3,
  'flags_extra': 67,
  'interval_nr': 0,
 'name': 'your_decimal_column',
...

Se field_type for igual a 0, então na tabela está sendo utilizado o antigo tipo — é necessário executar OPTIMIZE. No entanto, se o valor for 246 — você já tem um novo tipo. Você pode conferir mais sobre os tipos em código.

Além disso, neste bug é discutida uma segunda possível causa, que nos passou despercebida — a ausência de tabelas InnoDB na tabela de sistema INNODB_SYS_TABLESPACES , se essas tabelas foram criadas na versão 5.1. Para evitar problemas ao atualizar, você pode usaro script SQL anexo Por que não tivemos esses problemas no dev? O banco lá é periodicamente copiado do production — assim,.

as tabelas são recriadas Infelizmente, em um banco de dados grande em produção, não é possível simplesmente realizar um.

. Aqui, o percona-toolkit ajuda: para a operação online OPTIMIZE, a ferramenta pt-online-schema-change é perfeitamente adequada. OPTIMIZEO plano atualizado ficou assim:

Realizar a otimização de todas as tabelas.

  1. Realizar a atualização dos bancos de dados.
  2. Para verificar isso e ao mesmo tempo descobrir o tempo de atualização, desligamos uma das réplicas e para todas as tabelas executamos o seguinte comando:

pt-online-schema-change --critical-load Threads_running=150 --alter "ENGINE=InnoDB" --execute --chunk-size 100 --quiet --alter-foreign-keys-method auto h=127.0.0.1,u=root,p=${MYSQL_PASSWORD},D=db1,t=t1

pt-online-schema-change --critical-load Threads_running=150 --alter "ENGINE=InnoDB" --execute --chunk-size 100 --quiet --alter-foreign-keys-method auto h=127.0.0.1,u=root,p=${MYSQL_PASSWORD},D=db1,t=t1

A atualização das tabelas é realizada sem bloqueios prolongados, pois a ferramenta cria uma nova tabela temporária, na qual copia os dados da tabela principal. Assim que ambas as tabelas são idênticas, a tabela original é bloqueada e substituída pela nova. No nosso caso, o teste inicial mostrou que a atualização de todas as tabelas levaria cerca de um dia, mas a cópia de dados causou uma carga excessiva nos discos.

Para evitar isso, na produção, adicionamos à equipe o argumento --sleep com o valor 10 — esse parâmetro regula a duração da espera após a transferência de um lote de dados para a nova tabela. Isso pode reduzir a carga se o aplicativo em execução exigir um tempo de resposta ágil.

Após a execução da otimização, a atualização foi bem-sucedida.

… mas não completamente!

Já meia hora após a atualização, o cliente veio com um problema. O banco de dados estava funcionando de maneira estranha: periodicamente começaram a ocorrer resetes de conexões. Assim foi exibido no monitoramento:

Atualização do MySQL (Percona Server) de 5.7 para 8.0

No gráfico, é visível um padrão em forma de serra, relacionado ao fato de que algumas threads do servidor MySQL caíam periodicamente com erro. O aplicativo começou a apresentar erros:

[PDOException] SQLSTATE[HY000] [2002] Conexão recusada

Uma rápida inspeção dos logs revelou que o daemon mysqld não conseguia obter os recursos necessários do sistema operacional. Investigando os erros, descobrimos no sistema arquivos de políticas do apparmor "orfãos":

# dpkg -S /etc/apparmor.d/cache/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/cache/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/local/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/local/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/usr.sbin.mysqld
mysql-server-5.7: /etc/apparmor.d/usr.sbin.mysqld
# dpkg -l mysql-server-5.7
rc  mysql-server-5.7 5.7.23-0ubuntu0.16.04.1      amd64

Esses arquivos foram gerados durante a atualização para o MySQL 5.7 há alguns anos e pertencem a um pacote removido. A exclusão dos arquivos e o reinício do serviço apparmor resolveram o problema:

systemctl stop apparmor
rm /etc/apparmor.d/cache/usr.sbin.mysqld
rm /etc/apparmor.d/local/usr.sbin.mysqld
rm /etc/apparmor.d/usr.sbin.mysqld
systemctl start apparmor

Para concluir

Qualquer operação, mesmo a mais simples, pode levar a problemas inesperados. E até mesmo ter um plano bem elaborado nem sempre garante o resultado esperado. Agora, qualquer plano de atualização de nossa equipe inclui também a limpeza obrigatória de arquivos desnecessários que possam ter surgido como resultado das ações anteriores.

E com essa arte gráfica pouco profissional, gostaria de agradecer imensamente à empresa Percona pelos seus excelentes produtos!

Atualização do MySQL (Percona Server) de 5.7 para 8.0

P.S.

Confira também em nosso blog:

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster