Recomendações para recursos do MySQL no Aurora MySQL
Os recursos a seguir estão disponíveis no Aurora MySQL compatíveis com o MySQL. Contudo, eles apresentam problemas de performance, escalabilidade, estabilidade ou compatibilidade no ambiente do Aurora. Assim, recomendamos que você siga determinadas diretrizes no uso desses recursos. Por exemplo, recomendamos não usar determinados recursos para implantações de produção do Aurora.
Tópicos
Utilizar a replicação de vários threads no Aurora MySQL
Com a replicação de logs binários de vários threads, um thread SQL faz a leitura de eventos do log de retransmissão e coloca esses eventos em fila para que os threads de operador SQL sejam aplicados. Os threads de operador SQL são gerenciados por um thread coordenador. Os eventos de log binário são aplicados em paralelo sempre que possível.
A replicação de vários threads não é compatível com o Aurora MySQL versão 3 e o Aurora MySQL versão 2.12.1 e posterior.
Em relação às versões anteriores à 3.04 do Aurora MySQL, o Aurora usa replicação de um único thread por padrão quando um cluster de bancos de dados do Aurora MySQL é usado como uma réplica de leitura para replicação de log binário.
As versões anteriores do Aurora MySQL versão 2 herdaram alguns problemas relacionados à replicação de vários threads do MySQL Community Edition. Para essas versões, recomendamos não usar a replicação de vários threads em ambientes de produção.
Se você usa a replicação de vários threads, recomendamos testá-la completamente.
Para ter mais informações sobre o uso de replicação no Amazon Aurora, consulte Replicação com o Amazon Aurora. Para ter informações sobre a replicação de vários threads no Aurora MySQL, consulte Replicação de logs binários de vários threads.
Invocar funções do AWS Lambda com o uso de funções nativas do MySQL
Recomendamos usar as funções nativas do MySQL lambda_sync
e lambda_async
para invocar funções do Lambda.
Se você estiver usando o procedimento mysql.lambda_async
obsoleto, recomendamos que você faça chamadas do procedimento mysql.lambda_async
em um procedimento armazenado. Você pode chamar este procedimento armazenado a partir de origens diferentes, como triggers ou código do cliente. Essa abordagem pode ajudar a evitar problemas de incompatibilidade de impedância e facilita para seus programadores de banco de dados invocar funções do Lambda.
Para ter mais informações sobre como invocar funções do Lambda por meio do Amazon Aurora, consulte Invocar uma função do Lambda a partir de um cluster de banco de dados do Amazon Aurora MySQL.
Como evitar transações XA com o Amazon Aurora MySQL
Recomendamos que você não use transações eXtended Architecture (XA) com o Aurora MySQL, porque elas podem gerar longos tempos de recuperação se a XA estiver no estado PREPARED
. Se você precisa usar transações XA com o Aurora MySQL, siga estas práticas recomendadas:
-
Não deixe uma transação XA aberta no estado
PREPARED
. -
Mantenha as transações XA menores o possível.
Para ter mais informações sobre o uso de transações XA com o MySQL, consulte Transações XA
Como manter chaves externas ativadas durante instruções DML
Recomendamos que você não execute nenhuma instrução de linguagem de definição de dados (DDL) quando a variável foreign_key_checks
estiver definida como 0
(desativada).
Se você precisar inserir ou atualizar linhas que exigem uma violação transitória das chaves externas, siga estas etapas:
-
Defina
foreign_key_checks
como0
. -
Faça as alterações na sua linguagem de manipulação de dados (DML).
-
Verifique se as alterações realizadas não violam restrições de chaves externas.
-
Defina
foreign_key_checks
como1
(ativada).
Além disso, siga estas práticas recomendadas adicionais para restrições de chaves externas:
-
Verifique se suas aplicações cliente não definiram a variável
foreign_key_checks
como0
, como parte da variávelinit_connect
. -
Se a restauração a partir de um backup lógico, como
mysqldump
, apresentar falha ou não for concluída, definaforeign_key_checks
como1
antes de iniciar qualquer outra operação na mesma sessão. Um backup lógico defineforeign_key_checks
como0
ao ser inicializado.
Configurar a frequência com que o buffer de log é liberado
No MySQL Community Edition, para tornar as transações duráveis, o buffer de log do InnoDB deve ser liberado para um armazenamento durável. Use o parâmetro innodb_flush_log_at_trx_commit
para configurar a frequência com que o buffer de log é liberado para o disco.
Quando você define o parâmetro innodb_flush_log_at_trx_commit
como o valor padrão de 1, o buffer de log é liberado em cada confirmação de transação. Essa configuração ajuda a manter o banco de dados compatível com ACID
Alterar innodb_flush_log_at_trx_commit
para um valor não padrão pode ajudar a reduzir a latência da linguagem de manipulação de dados (DML), mas sacrifica a durabilidade dos registros de log. Essa falta de durabilidade torna o banco de dados incompatível com ACID. Recomendamos que seus bancos de dados estejam em conformidade com ACID para evitar o risco de perda de dados em caso de uma reinicialização do servidor. Para ter mais informações sobre esse parâmetro, consulte innodb_flush_log_at_trx_commit
No Aurora MySQL, o processamento de redo log é transferido para a camada de armazenamento, portanto, nenhuma descarga dos arquivos de log ocorre na instância de banco de dados. Quando uma gravação é emitida, os redo logs são enviados da instância de banco de dados do gravador diretamente ao volume do cluster do Aurora. As únicas gravações que atravessam a rede são os registros de redo log. Nenhuma página é gravada na camada do banco de dados.
Por padrão, cada thread que confirma uma transação aguarda a confirmação do volume do cluster do Aurora. Essa confirmação indica que esse registro e todos os registros anteriores de redo log foram gravados e atingiram o quórum
O Aurora MySQL não libera logs para arquivos de dados como o MySQL Community Edition. No entanto, você pode usar o parâmetro innodb_flush_log_at_trx_commit
para reduzir as restrições de durabilidade ao gravar registros de redo log no volume do cluster do Aurora.
Para o Aurora MySQL versão 2:
-
innodb_flush_log_at_trx_commit
= 0 ou 2: o banco de dados não espera pela confirmação de que os registros de log redo sejam gravados no volume do cluster do Aurora. -
innodb_flush_log_at_trx_commit
= 1: o banco de dados aguarda a confirmação de que os registros de log redo foram gravados no volume do cluster do Aurora.
Para o Aurora MySQL versão 3:
-
innodb_flush_log_at_trx_commit
= 0: o banco de dados não espera pela confirmação de que os registros de log redo sejam gravados no volume do cluster do Aurora. -
innodb_flush_log_at_trx_commit
= 1 ou 2: o banco de dados aguarda a confirmação de que os registros de log redo foram gravados no volume do cluster do Aurora.
Portanto, para obter o mesmo comportamento não padrão no Aurora MySQL versão 3 que seria obtido com o valor definido como 0 ou 2 no Aurora MySQL versão 2, defina o parâmetro como 0.
Embora essas configurações possam diminuir a latência do DML para o cliente, elas também podem ocasionar perda de dados no caso de failover ou reinicialização. Portanto, recomendamos que você mantenha o parâmetro innodb_flush_log_at_trx_commit
definido como o valor padrão de 1.
Embora a perda de dados possa ocorrer tanto no MySQL Community Edition quanto no Aurora MySQL, o comportamento difere em cada banco de dados devido às diferentes arquiteturas. Essas diferenças de arquitetura podem ocasionar vários graus de perda de dados. Para garantir que o banco de dados seja compatível com ACID, sempre defina innodb_flush_log_at_trx_commit
como 1.
nota
No Aurora MySQL versão 3, antes de alterar innodb_flush_log_at_trx_commit
para um valor diferente de 1, é necessário primeiro alterar o valor de innodb_trx_commit_allow_data_loss
para 1. Ao fazer isso, você reconhece o risco de perda de dados.
Minimizar e solucionar problemas de deadlocks do Aurora MySQL
Usuários que executam workloads que regularmente enfrentam violações de restrições em índices secundários exclusivos ou chaves estrangeiras, ao modificar registros na mesma página de dados simultaneamente, podem ter maiores deadlocks e tempos de espera de bloqueio. Esses deadlocks e tempos limite são causados por uma correção de bug
Essa correção está incluída nas versões 5.7.26 e posteriores do MySQL Community Edition e foi transferida para as versões 2.10.3 e posteriores do Aurora MySQL. A correção é necessária para reforçar a capacidade de serialização por meio da implementação de bloqueios adicionais para esses tipos de operação de linguagem de manipulação de dados (DML) nas alterações feitas nos registros em uma tabela do InnoDB. Esse problema foi descoberto como parte de uma investigação sobre problemas de deadlock introduzidos por uma correção de bug
A correção alterou o tratamento interno da reversão parcial de uma atualização de tupla (linha) no mecanismo de armazenamento InnoDB. Operações que geram violações de restrição em chaves estrangeiras ou índices secundários exclusivos causam reversão parcial. Isso inclui, entre outros, as instruções simultâneas INSERT...ON DUPLICATE KEY UPDATE
, REPLACE
INTO,
e INSERT IGNORE
(upserts).
Nesse contexto, a reversão parcial não se refere à reversão de transações em nível de aplicação, mas sim a uma reversão interna do InnoDB das alterações em um índice em cluster, quando uma violação de restrição é encontrada. Por exemplo, um valor de chave duplicado é encontrado durante uma operação de upsert.
Em uma operação normal de inserção, o InnoDB cria atomicamente entradas de índice secundárias e em cluster
Minimizar os deadlocks do InnoDB
Você pode adotar as abordagens a seguir para reduzir a frequência de deadlocks em sua instância de banco de dados. Mais exemplos podem ser encontrados na documentação do MySQL
-
Para reduzir as chances de deadlock, confirme as transações imediatamente depois de fazer um conjunto relacionado de alterações. Você pode fazer isso dividindo transações grandes (atualizações de várias linhas entre confirmações) em transações menores. Se você estiver inserindo linhas em lote, tente reduzir os tamanhos das inserções em lote, especialmente ao usar as operações de upsert mencionadas anteriormente.
Para reduzir o número de possíveis reversões parciais, você pode tentar algumas das seguintes abordagens:
-
Substitua as operações de inserção em lote pela inserção de uma linha por vez. Isso pode reduzir o tempo em que os bloqueios são mantidos por transações que podem ter conflitos.
-
Em vez de usar
REPLACE INTO
, reescreva a instrução SQL como uma transação com várias instruções, como a seguinte:BEGIN; DELETE
conflicting rows
; INSERTnew rows
; COMMIT; -
Em vez de usar
INSERT...ON DUPLICATE KEY UPDATE
, reescreva a instrução SQL como uma transação com várias instruções, como a seguinte:BEGIN; SELECT
rows that conflict on secondary indexes
; UPDATEconflicting rows
; INSERTnew rows
; COMMIT;
-
-
Evite transações de longa execução, ativas ou inativas, que possam ficar bloqueadas. Isso inclui sessões interativas do cliente MySQL que podem ficar abertas por um longo período com uma transação não confirmada. Ao otimizar os tamanhos das transações ou dos lotes, o impacto pode variar dependendo de vários fatores, como simultaneidade, número de duplicatas e estrutura da tabela. Todas as alterações devem ser implementadas e testadas com base em sua workload.
-
Em algumas situações, deadlocks podem ocorrer quando duas transações tentam acessar os mesmos conjuntos de dados, em uma ou várias tabelas, em ordens diferentes. Para evitar isso, você pode modificar as transações para acessar os dados na mesma ordem, serializando o acesso. Por exemplo, crie uma fila de transações a serem concluídas. Essa abordagem pode ajudar a evitar deadlocks quando ocorrem várias transações simultaneamente.
-
Adicionar índices cuidadosamente escolhidos às suas tabelas pode melhorar a seletividade e reduzir a necessidade de acessar linhas, o que ocasiona menos bloqueios.
-
Se você encontrar um bloqueio de lacunas
, poderá modificar o nível de isolamento da transação READ COMMITTED
para a sessão ou a transação a fim de evitá-lo. Para ter mais informações sobre os níveis de isolamento do InnoDB e seus comportamentos, consulte Níveis de isolamento de transaçõesna documentação do MySQL.
nota
Embora você possa tomar precauções para reduzir a possibilidade de ocorrência de deadlocks, eles são um comportamento esperado do banco de dados e ainda podem ocorrer. As aplicações devem ter a lógica necessária para lidar com deadlocks ao encontrá-los. Por exemplo, implemente a lógica de repetição e recuo na aplicação. É melhor resolver a causa raiz do problema, mas, se ocorrer um deadlock, a aplicação terá a opção de esperar e tentar novamente.
Monitorar deadlocks do InnoDB
Deadlocks
-
Instrução
SHOW ENGINE
: a instruçãoSHOW ENGINE INNODB STATUS \G
contém detalhesdo deadlock mais recente encontrado no banco de dados desde a última reinicialização. -
Log de erros do MySQL: se você encontrar deadlocks frequentes em que a saída da instrução
SHOW ENGINE
é inadequada, você poderá ativar o parâmetro de cluster de banco de dados innodb_print_all_deadlocks. Quando esse parâmetro é ativado, as informações sobre todos os deadlocks nas transações do usuário do InnoDB são registradas no log de erros
do Aurora MySQL. -
Métricas do Amazon CloudWatch: também recomendamos que você monitore proativamente os deadlocks usando a métrica do CloudWatch
Deadlocks
. Para ter mais informações, consulte Métricas no nível da instância do Amazon Aurora. -
Amazon CloudWatch Logs: com o CloudWatch Logs, você pode visualizar métricas, analisar dados de log e criar alarmes em tempo real. Para ter mais informações, consulte Monitorar erros no Amazon Aurora MySQL e no Amazon RDS para MySQL usando o Amazon CloudWatch e enviar notificações usando o Amazon SNS
. Usando o CloudWatch Logs com
innodb_print_all_deadlocks
ativado, você pode configurar alarmes para receber notificação quando o número de deadlocks exceder determinado limite. Para definir um limite, recomendamos que você observe suas tendências e use um valor com base em sua workload normal. -
Performance Insights: ao usar o Performance Insights, você pode monitorar as métricas
innodb_deadlocks
einnodb_lock_wait_timeout
. Para ter mais informações sobre essas métricas, consulte Contadores não nativos para o Aurora MySQL.