synch/cond/sql/MDL_context::COND_wait_status - Amazon Aurora

synch/cond/sql/MDL_context::COND_wait_status

O evento synch/cond/sql/MDL_context::COND_wait_status ocorre quando há threads aguardando em um bloqueio de metadados de tabela.

Versões compatíveis do mecanismo

Essas informações de eventos de espera têm suporte nas seguintes versões do mecanismo:

  • Aurora MySQL versão 2, até 2.09.2

  • Aurora MySQL versão 1, até 1.23.1

Contexto

O evento synch/cond/sql/MDL_context::COND_wait_status indica que há threads aguardando um bloqueio de metadados de tabela. Em alguns casos, uma sessão mantém um bloqueio de metadados em uma tabela, e outra sessão tenta obter o mesmo bloqueio na mesma tabela. Nesse caso, a segunda sessão aguarda no evento de espera synch/cond/sql/MDL_context::COND_wait_status.

O MySQL utiliza o bloqueio de metadados para gerenciar o acesso simultâneo a objetos de banco de dados e garantir a consistência dos dados. O bloqueio de metadados é aplicável a tabelas, esquemas, eventos agendados, espaços de tabelas e bloqueios de usuários adquiridos com a função get_lock e programas armazenados. Programas armazenados incluem procedimentos, funções e acionadores. Para obter mais informações, consulte o tópico sobre Bloqueio de metadados, na documentação do MySQL.

A lista de processos do MySQL mostra esta sessão no estado waiting for metadata lock. No Performance Insights, se Performance_schema estiver habilitado, o evento synch/cond/sql/MDL_context::COND_wait_status será exibido.

O tempo limite padrão para uma consulta aguardando um bloqueio de metadados baseia-se no valor do parâmetro lock_wait_timeout, cujo padrão é 31.536.000 segundos (365 dias).

Para obter mais detalhes sobre os diferentes bloqueios do InnoDB e os tipos de bloqueios que podem causar conflitos, consulte o tópico sobre Bloqueio do InnoDB, na documentação do MySQL.

Possíveis causas do maior número de esperas

Quando o evento synch/cond/sql/MDL_context::COND_wait_status aparece mais que o normal, possivelmente indicando um problema de performance, as causas típicas incluem:

Transações de longa execução

Uma ou mais transações estão modificando muitos dados e mantendo bloqueios nas tabelas por muito tempo.

Transações ociosas

Uma ou mais transações permanecem abertas por muito tempo, sem serem confirmadas ou revertidas.

Instruções DDL em tabelas grandes

Uma ou mais instruções de definição de dados (DDL), como comandos ALTER TABLE, foram executadas em tabelas muito grandes.

Bloqueios de tabela explícitos

Existem bloqueios explícitos em tabelas que não estão sendo liberados em tempo hábil. Por exemplo, uma aplicação pode executar instruções LOCK TABLE incorretamente.

Ações

Convém tomar medidas diferentes, dependendo das causas do evento de espera e da versão do cluster de banco de dados Aurora MySQL.

Identificar as sessões e as consultas que estão causando os eventos

É possível utilizar o Performance Insights para mostrar consultas bloqueadas pelo evento de espera synch/cond/sql/MDL_context::COND_wait_status. Porém, para identificar a sessão de bloqueio, consulte tabelas de metadados de performance_schema e information_schema no cluster de banco de dados.

Em geral, bancos de dados com carga de moderada a significativa apresentam eventos de espera. Os eventos de espera podem ser aceitáveis quando a performance é ideal. Se a performance não for ideal, examine onde o banco de dados está passando a maior parte do tempo. Observe os eventos de espera que contribuem para a carga mais alta e descubra se é possível otimizar o banco de dados e a aplicação para reduzir esses eventos.

Para localizar consultas SQL que são responsáveis pela carga alta
  1. Faça login no AWS Management Console e abra o console do Amazon RDS em https://console.aws.amazon.com/rds/.

  2. No painel de navegação, escolha Performance Insights.

  3. Escolha uma instância de banco de dados. O painel do Performance Insights dessa instância de banco de dados é exibido.

  4. No gráfico Database load (Carga de banco de dados), escolha Slice by wait (Segmentar por espera).

  5. Na parte inferior da página, escolha Top SQL (SQL principal).

    O gráfico mostra as consultas SQL que são responsáveis pela carga. Os que estão no topo da lista são os mais responsáveis. Para solucionar um gargalo, concentre-se nessas instruções.

Para obter uma visão geral útil da solução de problemas de uso do Performance Insights, consulte a AWSPublicação no blog de banco de dados sobre como Analisar workloads do Amazon Aurora MySQL com o Performance Insights.

Verifique se há eventos anteriores

É possível obter insights sobre esse evento de espera para conferir se há ocorrências passadas dele. Para isso, conclua as seguintes ações:

  • Verifique a linguagem de manipulação de dados (DML) e a taxa de transferência e latência de DDL para ver se houve alterações na workload.

    É possível utilizar o Performance Insights para encontrar consultas aguardando esse evento na ocasião do problema. Também é possível visualizar o resumo das consultas executadas próximo à ocorrência do problema.

  • Se logs de auditoria ou logs gerais estiverem habilitados para o cluster de banco de dados, será possível verificar todas as consultas executadas nos objetos (schema.table) envolvidos na transação em espera. Você também pode verificar consultas com execução concluída antes da transação.

As informações disponíveis para solucionar problemas com eventos anteriores são limitadas. A realização dessas verificações não mostra qual objeto está aguardando informações. No entanto, é possível identificar tabelas com alta carga na ocasião do evento e o conjunto de linhas operadas com frequência que estão causando conflito na ocasião do problema. Em seguida, você pode utilizar essas informações para reproduzir o problema em um ambiente de teste e fornecer insights sobre a sua causa.

Executar consultas no Aurora MySQL versão 1

No Aurora MySQL versão 1, é possível consultar tabelas em information_schema e performance_schema para identificar uma sessão de bloqueio. Para executar as consultas, verifique se o cluster de banco de dados está configurado com o consumidor performance_schema events_statements_history. Além disso, mantenha um número adequado de consultas na tabela events_statements_history em performance_schema. Controle o número de consultas mantidas nessa tabela com o parâmetro performance_schema_events_statements_history_size. Se os dados necessários não estiverem disponíveis em performance_schema, verifique os logs de auditoria ou logs gerais.

Um exemplo é capaz de ilustrar como consultar tabelas para identificar consultas e sessões de bloqueio. Neste exemplo, cada sessão executa menos de 10 instruções, e os consumidores necessários estão habilitados no cluster de banco de dados.

Na seguinte saída da lista de processos, o ID de processo 59 (executando o comando TRUNCATE) e o ID de processo 53 (executando o comando INSERT) estão aguardando um bloqueio de metadados por 33 segundos. Além disso, ambos os threads estão executando consultas na mesma tabela sbtest.sbtest1.

MySQL [(none)]> select @@version, @@aurora_version; +-----------+------------------+ | @@version | @@aurora_version | +-----------+------------------+ | 5.6.10 | 1.23.0 | +-----------+------------------+ 1 row in set (0.00 sec) MySQL [performance_schema]> select * from setup_consumers where name='events_statements_history'; +---------------------------+---------+ | NAME | ENABLED | +---------------------------+---------+ | events_statements_history | YES | +---------------------------+---------+ 1 row in set (0.00 sec) MySQL [performance_schema]> show global variables like 'performance_schema_events_statements_history_size'; +---------------------------------------------------+-------+ | Variable_name | Value | +---------------------------------------------------+-------+ | performance_schema_events_statements_history_size | 10 | +---------------------------------------------------+-------+ 1 row in set (0.00 sec) MySQL [performance_schema]> show processlist; +----+------------------+--------------------+--------------------+---------+------+---------------------------------+------------------------------------------------------------------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------------------+--------------------+--------------------+---------+------+---------------------------------+------------------------------------------------------------------------------------------------------+ | 11 | rdsadmin | localhost | NULL | Sleep | 0 | cleaned up | NULL | | 14 | rdsadmin | localhost | NULL | Sleep | 1 | cleaned up | NULL | | 15 | rdsadmin | localhost | NULL | Sleep | 14 | cleaned up | NULL | | 16 | rdsadmin | localhost | NULL | Sleep | 1 | cleaned up | NULL | | 17 | rdsadmin | localhost | NULL | Sleep | 214 | cleaned up | NULL | | 40 | auroramysql56123 | 172.31.21.51:44876 | sbtest123 | Query | 1843 | User sleep | select sleep(10000) | | 41 | auroramysql56123 | 172.31.21.51:44878 | performance_schema | Query | 0 | init | show processlist | | 48 | auroramysql56123 | 172.31.21.51:44894 | sbtest123 | Execute | 0 | delayed commit ok initiated | COMMIT | | 49 | auroramysql56123 | 172.31.21.51:44899 | sbtest123 | Execute | 0 | delayed commit ok initiated | COMMIT | | 50 | auroramysql56123 | 172.31.21.51:44896 | sbtest123 | Execute | 0 | delayed commit ok initiated | COMMIT | | 51 | auroramysql56123 | 172.31.21.51:44892 | sbtest123 | Execute | 0 | delayed commit ok initiated | COMMIT | | 52 | auroramysql56123 | 172.31.21.51:44898 | sbtest123 | Execute | 0 | delayed commit ok initiated | COMMIT | | 53 | auroramysql56123 | 172.31.21.51:44902 | sbtest | Query | 33 | Waiting for table metadata lock | INSERT INTO sbtest1 (id, k, c, pad) VALUES (0, 5021, '91560616281-61537173720-56678788409-8805377477 | | 56 | auroramysql56123 | 172.31.21.51:44908 | NULL | Query | 118 | User sleep | select sleep(10000) | | 58 | auroramysql56123 | 172.31.21.51:44912 | NULL | Sleep | 41 | cleaned up | NULL | | 59 | auroramysql56123 | 172.31.21.51:44914 | NULL | Query | 33 | Waiting for table metadata lock | truncate table sbtest.sbtest1 | +----+------------------+--------------------+--------------------+---------+------+---------------------------------+------------------------------------------------------------------------------------------------------+ 16 rows in set (0.00 sec)

Considerando essa saída, execute a consulta a seguir. Essa consulta identifica transações que estão sendo executadas há mais de 33 segundos com o ID de conexão 59 aguardando um bloqueio em uma tabela pelo mesmo período.

MySQL [performance_schema]> select b.id, a.trx_id, a.trx_state, a.trx_started, TIMESTAMPDIFF(SECOND,a.trx_started, now()) as "Seconds Transaction Has Been Open", a.trx_rows_modified, b.USER, b.host, b.db, b.command, b.time, b.state from information_schema.innodb_trx a, information_schema.processlist b where a.trx_mysql_thread_id=b.id and TIMESTAMPDIFF(SECOND,a.trx_started, now()) > 33 order by trx_started; +----+---------+-----------+---------------------+-----------------------------------+-------------------+------------------+--------------------+-----------+---------+------+------------+ | id | trx_id | trx_state | trx_started | Seconds Transaction Has Been Open | trx_rows_modified | USER | host | db | command | time | state | +----+---------+-----------+---------------------+-----------------------------------+-------------------+------------------+--------------------+-----------+---------+------+------------+ | 40 | 1907737 | RUNNING | 2021-02-02 12:58:16 | 1955 | 0 | auroramysql56123 | 172.31.21.51:44876 | sbtest123 | Query | 1955 | User sleep | | 56 | 3797992 | RUNNING | 2021-02-02 13:27:01 | 230 | 0 | auroramysql56123 | 172.31.21.51:44908 | NULL | Query | 230 | User sleep | | 58 | 3895074 | RUNNING | 2021-02-02 13:28:18 | 153 | 0 | auroramysql56123 | 172.31.21.51:44912 | NULL | Sleep | 153 | cleaned up | +----+---------+-----------+---------------------+-----------------------------------+-------------------+------------------+--------------------+-----------+---------+------+------------+ 3 rows in set (0.00 sec)

Na saída, os processos 40, 56 e 58 estão ativos há muito tempo. Vamos identificar consultas executadas por essas sessões na tabela sbtest.sbtest1.

MySQL [performance_schema]> select t.processlist_id, t.thread_id, sql_text from performance_schema.threads t join events_statements_history sh on t.thread_id=sh.thread_id where processlist_id in (40,56,58) and SQL_TEXT like '%sbtest1%' order by 1; +----------------+-----------+------------------------------------------+ | processlist_id | thread_id | sql_text | +----------------+-----------+------------------------------------------+ | 56 | 84 | select * from sbtest123.sbtest10 limit 1 | | 58 | 86 | select * from sbtest.sbtest1 limit 1 | +----------------+-----------+------------------------------------------+ 2 rows in set (0.01 sec)

Nessa saída, a sessão com processlist_id de 58 executou uma consulta na tabela e mantém uma transação aberta. Essa transação aberta está bloqueando o comando TRUNCATE.

Executar consultas no Aurora MySQL versão 2

No Aurora MySQL versão 2, é possível identificar a sessão bloqueada diretamente, consultando tabelas performance_schema ou visualizações de esquema sys. Um exemplo é capaz de ilustrar como consultar tabelas para identificar consultas e sessões de bloqueio.

Na saída da lista de processos a seguir, o ID da conexão 89 está aguardando um bloqueio de metadados e está executando um comando TRUNCATE TABLE. Em uma consulta nas tabelas performance_schema ou visualizações de esquema sys, a saída mostra que a sessão de bloqueio é 76.

MySQL [(none)]> select @@version, @@aurora_version; +-----------+------------------+ | @@version | @@aurora_version | +-----------+------------------+ | 5.7.12 | 2.09.0 | +-----------+------------------+ 1 row in set (0.01 sec) MySQL [(none)]> show processlist; +----+-----------------+--------------------+-----------+---------+------+---------------------------------+-------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+-----------------+--------------------+-----------+---------+------+---------------------------------+-------------------------------+ | 2 | rdsadmin | localhost | NULL | Sleep | 0 | NULL | NULL | | 4 | rdsadmin | localhost | NULL | Sleep | 2 | NULL | NULL | | 5 | rdsadmin | localhost | NULL | Sleep | 1 | NULL | NULL | | 20 | rdsadmin | localhost | NULL | Sleep | 0 | NULL | NULL | | 21 | rdsadmin | localhost | NULL | Sleep | 261 | NULL | NULL | | 66 | auroramysql5712 | 172.31.21.51:52154 | sbtest123 | Sleep | 0 | NULL | NULL | | 67 | auroramysql5712 | 172.31.21.51:52158 | sbtest123 | Sleep | 0 | NULL | NULL | | 68 | auroramysql5712 | 172.31.21.51:52150 | sbtest123 | Sleep | 0 | NULL | NULL | | 69 | auroramysql5712 | 172.31.21.51:52162 | sbtest123 | Sleep | 0 | NULL | NULL | | 70 | auroramysql5712 | 172.31.21.51:52160 | sbtest123 | Sleep | 0 | NULL | NULL | | 71 | auroramysql5712 | 172.31.21.51:52152 | sbtest123 | Sleep | 0 | NULL | NULL | | 72 | auroramysql5712 | 172.31.21.51:52156 | sbtest123 | Sleep | 0 | NULL | NULL | | 73 | auroramysql5712 | 172.31.21.51:52164 | sbtest123 | Sleep | 0 | NULL | NULL | | 74 | auroramysql5712 | 172.31.21.51:52166 | sbtest123 | Sleep | 0 | NULL | NULL | | 75 | auroramysql5712 | 172.31.21.51:52168 | sbtest123 | Sleep | 0 | NULL | NULL | | 76 | auroramysql5712 | 172.31.21.51:52170 | NULL | Query | 0 | starting | show processlist | | 88 | auroramysql5712 | 172.31.21.51:52194 | NULL | Query | 22 | User sleep | select sleep(10000) | | 89 | auroramysql5712 | 172.31.21.51:52196 | NULL | Query | 5 | Waiting for table metadata lock | truncate table sbtest.sbtest1 | +----+-----------------+--------------------+-----------+---------+------+---------------------------------+-------------------------------+ 18 rows in set (0.00 sec)

Em seguida, uma consulta nas tabelas performance_schema ou visualizações de esquema sys mostra que a sessão de bloqueio é 76.

MySQL [(none)]> select * from sys.schema_table_lock_waits; +---------------+-------------+-------------------+-------------+------------------------------+-------------------+-----------------------+-------------------------------+--------------------+-----------------------------+-----------------------------+--------------------+--------------+------------------------------+--------------------+------------------------+-------------------------+------------------------------+ | object_schema | object_name | waiting_thread_id | waiting_pid | waiting_account | waiting_lock_type | waiting_lock_duration | waiting_query | waiting_query_secs | waiting_query_rows_affected | waiting_query_rows_examined | blocking_thread_id | blocking_pid | blocking_account | blocking_lock_type | blocking_lock_duration | sql_kill_blocking_query | sql_kill_blocking_connection | +---------------+-------------+-------------------+-------------+------------------------------+-------------------+-----------------------+-------------------------------+--------------------+-----------------------------+-----------------------------+--------------------+--------------+------------------------------+--------------------+------------------------+-------------------------+------------------------------+ | sbtest | sbtest1 | 121 | 89 | auroramysql5712@192.0.2.0 | EXCLUSIVE | TRANSACTION | truncate table sbtest.sbtest1 | 10 | 0 | 0 | 108 | 76 | auroramysql5712@192.0.2.0 | SHARED_READ | TRANSACTION | KILL QUERY 76 | KILL 76 | +---------------+-------------+-------------------+-------------+------------------------------+-------------------+-----------------------+-------------------------------+--------------------+-----------------------------+-----------------------------+--------------------+--------------+------------------------------+--------------------+------------------------+-------------------------+------------------------------+ 1 row in set (0.00 sec)

Responder à sessão de bloqueio

Ao identificar a sessão, suas opções incluem:

  • Entre em contato com o proprietário da aplicação ou o usuário.

  • Se a sessão de bloqueio estiver ociosa, considere encerrá-la. Essa ação pode desencadear uma reversão longa. Para aprender a encerrar uma sessão, consulte o tópico sobre como Encerrar uma sessão ou consulta, no Guia do usuário do Amazon RDS.

Para obter mais informações sobre como identificar transações de bloqueio, consulte o tópico sobre como Utilizar informações de transações e bloqueios do InnoDB, na documentação do MySQL.