Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Problema de deadlock do MySQL com InnoDB


Isso está causando um impasse porque o UPDATE query está bloqueando todas as linhas da tabela e, dependendo dos índices usados ​​(ou da falta deles), duas sessões diferentes potencialmente os bloquearão em uma ordem ligeiramente diferente. Lembre-se que UPDATE , DELETE e SELECT ... FOR UPDATE bloqueará todas as linhas que encontrarem, se essas linhas corresponderem a todos os WHERE condições ou não. Portanto, ao usá-los, você deve se esforçar para garantir que eles encontrem o menor número de linhas possível, usando índices (idealmente a chave primária) e evitando condições vagas ou de seleção ampla.

Minha sugestão para filas de trabalho é praticamente universal:bloqueie o mínimo possível, o mais raramente possível e sempre em uma ordem determinística. Então, geralmente:
  1. Use leituras sem travamento (regular SELECT ) para encontrar trabalho para fazer procurando por coisas que seu funcionário sabe fazer e não foi reivindicado no momento (lease_owner IS NULL AND lease_expiry IS NULL -- ou similar).
  2. Escolha um item de trabalho (ou alguns, se tiver coragem, mas um é muito mais simples e normalmente permite um desempenho perfeitamente aceitável).
  3. Atualize seu item de trabalho (para reivindicá-lo, mas, em qualquer caso, ele também precisa ser atualizado):
    1. Abra uma transação.
    2. Bloqueie o item de trabalho escolhido com SELECT ... FOR UPDATE -- Se não for mais reclamado, cancele e escolha outro.
    3. Atualize o item de trabalho escolhido com seu ID de trabalhador e um prazo de validade para o seu aluguel.
    4. Confirme sua transação imediatamente.
  4. Comece a trabalhar em seus itens de trabalho alugados.
  5. Em algum outro processo, outro pesquisador procura um trabalho abandonado e o cancela (pelo mesmo processo de atualização acima).

Você pode facilmente obter uma taxa de transferência muito alta com esse design (milhares de trabalhos por segundo) e essencialmente sem contenção e sem problemas de pedido. As otimizações para escolher o trabalho com menos probabilidade de entrar em conflito com outros pesquisadores são simples e eficazes (por exemplo, módulo no ID do trabalho ou similar, escolhido para evitar a fome de trabalhos). A chave é lembrar que o conflito na seleção do trabalho é ok -- apenas aborte e tente novamente e tudo se move muito rapidamente.

Todas as gravações de bloqueio para itens/trabalhos da fila de trabalho devem ser feitas apenas em linhas únicas e por chave primária somente .