Recomendações para recursos do MySQL no Aurora MySQL - Amazon Aurora

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.

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 na documentação do MySQL.

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:

  1. Defina foreign_key_checks como 0.

  2. Faça as alterações na sua linguagem de manipulação de dados (DML).

  3. Verifique se as alterações realizadas não violam restrições de chaves externas.

  4. Defina foreign_key_checks como 1 (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 como 0, como parte da variável init_connect.

  • Se a restauração a partir de um backup lógico, como mysqldump, apresentar falha ou não for concluída, defina foreign_key_checks como 1 antes de iniciar qualquer outra operação na mesma sessão. Um backup lógico define foreign_key_checks como 0 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. Recomendamos que você mantenha a configuração padrão 1.

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 na documentação do MySQL.

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. A persistência dos registros de log e a obtenção do quórum tornam a transação durável, seja por meio de confirmação automática ou confirmação explícita. Para ter mais informações sobre a arquitetura de armazenamento do Aurora, consulte Amazon Aurora storage demystified (Armazenamento desmistificado do Amazon Aurora).

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 do MySQL Community Edition.

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 anterior do MySQL Community Edition.

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 para cada índice. Se o InnoDB detectar um valor duplicado em um índice secundário exclusivo durante uma operação de upsert, a entrada inserida no índice em cluster deverá ser revertida (reversão parcial) e a atualização deverá ser aplicada à linha duplicada existente. Durante essa etapa interna de reversão parcial, o InnoDB deve bloquear cada registro visto como parte da operação. A correção garante a capacidade de serialização da transação ao introduzir bloqueios adicionais após a reversão parcial.

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.

  1. 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:

    1. 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.

    2. 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; INSERT new rows; COMMIT;
    3. 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; UPDATE conflicting rows; INSERT new rows; COMMIT;
  2. 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.

  3. 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.

  4. Adicionar índices cuidadosamente escolhidos às suas tabelas pode melhorar a seletividade e reduzir a necessidade de acessar linhas, o que ocasiona menos bloqueios.

  5. 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ções na 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 podem ocorrer no MySQL quando as transações da aplicação tentam fazer um bloqueio em nível de tabela e linha de uma forma que resulta em espera circular. Um deadlock ocasional do InnoDB não é necessariamente um problema, porque o mecanismo de armazenamento do InnoDB detecta a condição imediatamente e reverte uma das transações de forma automática. Se você se deparar com deadlocks com frequência, recomendamos revisar e modificar sua aplicação para amenizar problemas de performance e evitá-los. Quando a detecção de deadlocks está ativada (o padrão), o InnoDB os detecta automaticamente nas transações e reverte uma ou mais transações para romper o deadlock. O InnoDB tenta selecionar pequenas transações para reverter, caso em que o tamanho de uma transação é determinado pelo número de linhas inseridas, atualizadas ou excluídas.

  • Instrução SHOW ENGINE: a instrução SHOW ENGINE INNODB STATUS \G contém detalhes do 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 e innodb_lock_wait_timeout. Para ter mais informações sobre essas métricas, consulte Contadores não nativos para o Aurora MySQL.