A latência de E/S pode fazer com que um simples UPDATE leve segundos no MySQL?

StackOverflow https://stackoverflow.com//questions/9655638

  •  11-12-2019
  •  | 
  •  

Pergunta

Meu aplicativo MySQL está apresentando desempenho lento ao executar alguns UPDATE, INSERT e DELETE consultas.Nesta questão, discutirei apenas um particular UPDATE, porque é suficiente para demonstrar o problema:

UPDATE projects SET ring = 5 WHERE id = 1

Esse UPDATE geralmente é rápido o suficiente, em torno de 0,2 ms, mas de vez em quando (o suficiente para ser um problema) leva vários segundos.Aqui está um trecho do log (veja a 4ª linha):

 ~ (0.000282) UPDATE `projects` SET `ring` = 5 WHERE `id` = 1
 ~ (0.000214) UPDATE `projects` SET `ring` = 6 WHERE `id` = 1
 ~ (0.000238) UPDATE `projects` SET `ring` = 7 WHERE `id` = 1
 ~ (3.986502) UPDATE `projects` SET `ring` = 8 WHERE `id` = 1
 ~ (0.000186) UPDATE `projects` SET `ring` = 9 WHERE `id` = 1
 ~ (0.000217) UPDATE `projects` SET `ring` = 0 WHERE `id` = 1
 ~ (0.000162) UPDATE `projects` SET `ring` = 1 WHERE `id` = 1

projects é uma tabela InnoDB com 6 colunas de tipos INT e VARCHAR, 17 linhas e um índice em id.Acontece com outras tabelas também, mas aqui estou focando nesta.Ao tentar resolver o problema, garanti que as consultas fossem todas sequenciais, então isso é não é um problema de bloqueio.O UPDATE acima é executado no contexto de uma transação.Outro informações no servidor:

  • VPS com 4 GB de RAM (era 1 GB), 12 GB de espaço livre em disco
  • CentoOS 5.8 (era 5.7)
  • MySQL 5.5.10 (era 5.0.x)

O bit “era” acima significa que não funcionou antes ou depois da atualização.

O que tentei até agora, sem sucesso:

  • Contexto innodb_flush_log_at_trx_commit para 0, 1 ou 2
  • Contexto innodb_locks_unsafe_for_binlog ligado ou desligado
  • Contexto timed_mutexes ligado ou desligado
  • Mudando innodb_flush_method do padrão para O_DSYNC ou O_DIRECT
  • Aumentando innodb_buffer_pool_size do padrão para 600M e depois para 3000M
  • Aumentando innodb_log_file_size do padrão para 128M
  • Compilando MySQL a partir do código-fonte
  • Correndo SHOW PROCESSLIST, que me informa que o estado está "atualizando"
  • Correndo SHOW PROFILE ALL, que diz que quase todo o tempo foi gasto em "atualização" e que, dentro dessa etapa, não foi gasto tanto tempo em ciclos de CPU e houve muitas trocas voluntárias de contexto (como 30)
  • Monitoramento SHOW STATUS para mudanças em Innodb_buffer_pool_pages_dirty.Pode haver alguma relação entre a liberação de páginas sujas e as consultas lentas, mas a correlação não é clara.

Então decidi verificar a latência de E/S do sistema com ioping.Este é meu primeiro VPS, então Fiquei surpreso ao ver esse resultado:

4096 bytes from . (vzfs /dev/vzfs): request=1 time=249.2 ms
4096 bytes from . (vzfs /dev/vzfs): request=2 time=12.3 ms
4096 bytes from . (vzfs /dev/vzfs): request=3 time=110.5 ms
4096 bytes from . (vzfs /dev/vzfs): request=4 time=232.8 ms
4096 bytes from . (vzfs /dev/vzfs): request=5 time=294.4 ms
4096 bytes from . (vzfs /dev/vzfs): request=6 time=704.7 ms
4096 bytes from . (vzfs /dev/vzfs): request=7 time=1115.0 ms
4096 bytes from . (vzfs /dev/vzfs): request=8 time=209.7 ms
4096 bytes from . (vzfs /dev/vzfs): request=9 time=64.2 ms
4096 bytes from . (vzfs /dev/vzfs): request=10 time=396.2 ms

Bastante errático, eu diria.

Dito tudo isso, pergunto:

  1. A latência de E/S pode ocasionalmente prejudicar o desempenho do MySQL? Sempre pensei que, quando você dirigia um UPDATE, o thread que cuidava dessa conexão não iria descarregar os dados para o disco ou esperar por tal liberação;ele retornaria imediatamente e a liberação seria feita por outro thread em outro momento.

  2. Se não puder ser E/S de disco, há mais alguma coisa que eu possa tentar, além de alugar um servidor dedicado?

Foi útil?

Solução

Estou respondendo à minha própria pergunta com dados adicionais que coletei com base nas suas respostas.

Utilizei dois notebooks conectados por meio de uma rede wireless.No caderno A, I montou um diretório do notebook B usando sshfs.Aí no caderno A eu comecei MySQL especificando esse diretório montado como seu diretório de dados.Isso deve fornecer MySQL com um dispositivo de E/S muito lento.MySQL foi iniciado cominnodb_flush_log_at_trx_commit = 0.

Defini 3 conjuntos de consultas, cada conjunto consistindo em uma atualização e uma consulta de seleção repetidas 10.000 vezes, sem transações explícitas.Os experimentos foram:

  • US1SID:atualize e selecione em uma linha específica da mesma tabela.A mesma linha foi usado em todas as iterações.
  • EUA1MID:atualize e selecione em uma linha específica da mesma tabela.A fila era uma diferente em cada iteração.
  • EUA2MID:atualize e selecione em linhas de tabelas diferentes.Neste caso, a tabela ser lido pelo selecionado não mudou em nada durante o experimento.

Cada conjunto foi executado duas vezes usando um script de shell (portanto, os tempos são mais lentos que os da minha pergunta original), um em condições normais e outro após executar o seguinte comando:

tc qdisc replace dev wlan0 root handle 1:0 netem delay 200ms

O comando acima adiciona um atraso médio de 200ms ao transmitir pacotes através do wlan0.

Primeiro, aqui está o tempo médio das 99% mais rápidas atualizações e seleções, e o 1% inferior atualiza e seleciona.

          |        Delay: 0ms        |       Delay: 200ms       |
          | US1SID | US1MID | US2MID | US1SID | US1MID | US2MID |
| top99%u | 0.0064 | 0.0064 | 0.0064 | 0.0063 | 0.0063 | 0.0063 |
| top99%s | 0.0062 | 0.0063 | 0.0063 | 0.0062 | 0.0062 | 0.0062 |
| bot01%u | 1.1834 | 1.2239 | 0.9561 | 1.9461 | 1.7492 | 1.9731 |
| bot01%s | 0.4600 | 0.5391 | 0.3417 | 1.4424 | 1.1557 | 1.6426 |

Como é claro, mesmo com um desempenho de E/S muito, muito ruim, o MySQL consegue Execute a maioria das consultas muito rápido.Mas o que mais me preocupa é o pior casos, então aqui está outra tabela, mostrando as 10 consultas mais lentas.Um "u" significa isso foi uma atualização, um "s" uma seleção.

|          Delay: 0ms         |          Delay: 200ms          |
| US1SID  | US1MID  | US2MID  | US1SID   | US1MID   | US2MID   |
| 5.443 u | 5.946 u | 5.315 u | 11.500 u | 10.860 u | 11.424 s |
| 5.581 u | 5.954 s | 5.466 u | 11.649 s | 10.995 u | 11.496 s |
| 5.863 s | 6.291 u | 5.658 u | 12.551 s | 11.020 u | 12.221 s |
| 6.192 u | 6.513 u | 5.685 u | 12.893 s | 11.370 s | 12.599 u |
| 6.560 u | 6.521 u | 5.736 u | 13.526 u | 11.387 u | 12.803 u |
| 6.562 u | 6.555 u | 5.743 u | 13.997 s | 11.497 u | 12.920 u |
| 6.872 u | 6.575 u | 5.869 u | 14.662 u | 12.825 u | 13.625 u |
| 6.887 u | 7.908 u | 5.996 u | 19.953 u | 12.860 u | 13.828 s |
| 6.937 u | 8.100 u | 6.330 u | 20.623 u | 14.015 u | 16.292 u |
| 8.665 u | 8.298 u | 6.893 u | 27.102 u | 22.042 s | 17.131 u |

Conclusões:

  1. O baixo desempenho de E/S pode de fato retardar o MySQL.Não está claro por queou quando exatamente, mas isso acontece.

  2. A lentidão se aplica a seleções e atualizações, com atualizações sofrendo mais.

  3. Por algum motivo, até seleciona em uma mesa que não estava envolvida em nenhuma mudança, e que haviam sido recentemente povoadas, também foram desaceleradas, como é claro de US2MID acima.

  4. Quanto aos casos de teste propostos por mentatkgs, parece que a atualização diferente linhas em vez das mesmas ajuda um pouco, mas não resolve o problema.

Acho que vou adaptar meu software para tolerar tais atrasos ou tentar me mover para outro provedor.Alugar um servidor dedicado é muito caro para isso projeto.

Obrigado a todos pelos comentários.

Outras dicas

Ao hospedar seu VPS na nuvem, você pode se deparar com problemas que estão completamente fora de seu controle.

Os VPSs estão sujeitos aos caprichos dos servidores host que os executam.Por exemplo, a prioridade do ciclo da CPU na Rackspace Cloud é ponderada com base no tamanho do VPS.Quanto maior for o seu VPS, maior será a probabilidade de o seu aplicativo funcionar sem problemas.Se houver um VPS maior no host que você está usando, é possível que a culpa é da explosão ponderada.É muito difícil dizer.

Você já tentou executar isso localmente em sua própria máquina?Se funcionar perfeitamente em seu próprio sistema e você precisar de desempenho garantido, sua melhor aposta será mudar para um servidor dedicado.

Você tem um problema de IO relacionado ao VPS.Não é culpa do MySQL.

Por acaso você está usando Elastic Block Store com Amazon ou possivelmente RDS?Ambos usam armazenamento remoto e uma camada de protocolo IP para se comunicar com o armazenamento;eles podem ter um atraso desagradável às vezes.

Pergunta 1) Sim.

Para verificar, escreva 2 aplicativos:

Caso de teste 1:farei isso a cada minuto por algumas horas

UPDATE `projects` SET `ring` = 5 WHERE `id` = 1
UPDATE `projects` SET `ring` = 6 WHERE `id` = 1

Caso de teste 2:farei isso a cada minuto por algumas horas

UPDATE `projects` SET `ring` = 7 WHERE `id` = 1
UPDATE `projects` SET `ring` = 8 WHERE `id` = 2

O caso de teste 1 deve ter um atraso, enquanto o caso de teste 2 não.

Questão 2) Use um banco de dados noSQL.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top