
Recentemente, atualizamos nossos servidores do MySQL 5.7 para 8.0.
Vamos deixar de fora o escopo deste artigo, por que e quais novos pães apareceram no MySQL 8.0, mas, em vez disso, falaremos sobre as dificuldades que encontramos durante o processo de atualização.
Em primeiro lugar, antes de atualizar, vale a pena examinar a
lista de alterações e corrigir o seu arquivo de configuração.
No mínimo, as seguintes opções foram excluídas:
innodb_file_format, innodb_file_format_check, innodb_file_format_max, innodb_large_prefix
query_cache_limit, query_cache_min_res_unit, query_cache_size, query_cache_type, query_cache_wlock_invalidate.
No parâmetro sql_mode, em particular, NO_AUTO_CREATE_USER foi excluído - o que é especialmente importante, porque no MySQL 5.7, estava ativado por padrão.
A Percona possui instruções para atualização no local. E, no caso geral, você pode segui-lo, no entanto, conseguimos atualizar apenas um cluster dessa maneira; de resto, uma tentativa de atualizar isso falhou com um erro semelhante:
2019-06-22T05:04:18.510888Z 1 [ERROR] [MY-011014] [Server] Found partially upgraded DD. Aborting upgrade and deleting all DD tables. Start the upgrade process again. 2019-06-22T05:04:23.115018Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed. 2019-06-22T05:04:23.115655Z 0 [ERROR] [MY-010119] [Server] Aborting
Portanto, atualizamos os clusters restantes, criando uma nova instância vazia e restaurando o dump do banco de dados da versão anterior.
Para fazer isso, primeiro, você precisa de um despejo de banco de dados. E aqui o perigo # 1 aguarda - um despejo feito da maneira padrão:
mysqldump -u root -p --hex-blob --default-character-set=utf8mb4 --all-databases --triggers --routines --events > dump.sql
não se recupera dando um erro:
ERROR 3554 (HY000) at line 15915: Access to system table 'mysql.innodb_index_stats' is rejected.
A descrição está
no rastreador de erros do MySQL (com o status Not a bug :), também há conselhos sobre como despejá-lo para que possa ser restaurado:
mysqldump -u root -p --hex-blob --default-character-set=utf8mb4 --all-databases --triggers --routines --events --ignore-table=mysql.innodb_index_stats --ignore-table=mysql.innodb_table_stats > dump.sql
Mas, ao tentar usar esse despejo, se houvesse gatilhos (e nós os tínhamos), o perigo número 2 poderia ser esperado, na forma de um erro:
ERROR 1231 (42000) at line 54: Variable 'sql_mode' can't be set to the value of 'NO_AUTO_CREATE_USER'
A razão para isso é porque o MySQL usa sql_mode para acionadores, a saber: O MySQL salva o valor sql_mode para o acionador no momento em que é criado e, em seguida, sempre o executa com esse valor. E, consequentemente, salva esse valor em um despejo.
Descrição da ajuda para isso:
dev.mysql.com/doc/refman/8.0/en/create-trigger.html
O MySQL armazena a configuração da variável de sistema sql_mode em vigor quando um gatilho é criado e sempre executa o corpo do gatilho com essa configuração em vigor, independentemente do modo SQL do servidor atual quando o gatilho começa a ser executado.
O que fazemos? Acabamos de cortar NO_AUTO_CREATE_USER do despejo finalizado. Comando semelhante:
sed "s/50003 SET sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER/50003 SET sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO/g" dump.sql > dump2.sql
Depois disso, o dump é restaurado com sucesso, mas o perigo nº 3 nos espera (a verdade esperada) - as tabelas do sistema foram restauradas para o estado a partir da versão 5.7 e temos os seguintes erros nos logs:
[ERROR] [MY-013143] [Server] Column count of mysql.user is wrong. Expected 51, found 45. The table is probably corrupted
Da experiência com versões anteriores, isso é tratado executando mysql_upgrade - mas desde a versão 8.0.16 - isso não funciona, porque mysql_upgrade é declarado obsoleto e não faz nada.
Agora, para fazer com que as tabelas do sistema sejam atualizadas, você deve iniciar o MySQL com a opção
upgrade = FORCE .
No ubuntu novo, isso pode ser feito da seguinte maneira:
systemctl set-environment MYSQLD_OPTS="--upgrade=FORCE"
Então reinicie o MySQL. Bem, após uma atualização bem-sucedida, exclua-a:
systemctl unset-environment MYSQLD_OPTS