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