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

Como evitar o MySQL 'Deadlock encontrado ao tentar obter o bloqueio; tente reiniciar a transação'


Um truque fácil que pode ajudar na maioria dos impasses é classificar as operações em uma ordem específica.

Você obtém um deadlock quando duas transações estão tentando bloquear dois bloqueios em ordens opostas, ou seja:
  • conexão 1:chave de bloqueio(1), chave de bloqueio(2);
  • conexão 2:trava chave(2), trava chave(1);

Se ambas forem executadas ao mesmo tempo, a conexão 1 bloqueará a tecla (1), a conexão 2 bloqueará a tecla (2) e cada conexão aguardará que a outra libere a tecla -> deadlock.

Agora, se você alterou suas consultas de forma que as conexões travassem as chaves na mesma ordem, ou seja:
  • conexão 1:chave de bloqueio(1), chave de bloqueio(2);
  • conexão 2:chave de bloqueio(1 ), chave de bloqueio(2 );

será impossível obter um impasse.

Então é isso que eu sugiro:

  1. Certifique-se de que não haja outras consultas que bloqueiem o acesso a mais de uma chave por vez, exceto a instrução delete. se você fizer (e eu suspeito que sim), ordene o WHERE em (k1,k2,..kn) em ordem crescente.

  2. Corrija sua instrução de exclusão para funcionar em ordem crescente:

Mudar
DELETE FROM onlineusers 
WHERE datetime <= now() - INTERVAL 900 SECOND

Para
DELETE FROM onlineusers 
WHERE id IN (
    SELECT id FROM onlineusers
    WHERE datetime <= now() - INTERVAL 900 SECOND 
    ORDER BY id
) u;

Outra coisa a ter em mente é que a documentação do MySQL sugere que no caso de um impasse o cliente deve tentar novamente automaticamente. você pode adicionar essa lógica ao seu código de cliente. (Diga, 3 tentativas neste erro específico antes de desistir).