sql >> Base de Datos >  >> RDS >> Mysql

Cómo evitar MySQL 'Se encontró un punto muerto al intentar obtener el bloqueo; intente reiniciar la transacción'

Un truco fácil que puede ayudar con la mayoría de los interbloqueos es clasificar las operaciones en un orden específico.

Obtiene un interbloqueo cuando dos transacciones intentan bloquear dos bloqueos en órdenes opuestas, es decir:

  • conexión 1:tecla de bloqueo(1), tecla de bloqueo(2);
  • conexión 2:tecla de bloqueo (2), tecla de bloqueo (1);

Si ambos se ejecutan al mismo tiempo, la conexión 1 bloqueará la tecla (1), la conexión 2 bloqueará la tecla (2) y cada conexión esperará a que la otra libere la tecla -> interbloqueo.

Ahora, si cambiaste tus consultas de modo que las conexiones bloquearan las claves en el mismo orden, es decir:

  • conexión 1:tecla de bloqueo(1), tecla de bloqueo(2);
  • conexión 2:llave de bloqueo (1 ), llave de bloqueo (2 );

será imposible conseguir un interbloqueo.

Así que esto es lo que sugiero:

  1. Asegúrese de que no tenga otras consultas que bloqueen el acceso a más de una clave a la vez, excepto la declaración de eliminación. si lo hace (y sospecho que lo hace), ordene su DÓNDE en (k1,k2,..kn) en orden ascendente.

  2. Corrija su declaración de eliminación para que funcione en orden ascendente:

Cambiar

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;

Otra cosa a tener en cuenta es que la documentación de MySQL sugiere que, en caso de bloqueo, el cliente debe volver a intentarlo automáticamente. puede agregar esta lógica a su código de cliente. (Digamos, 3 reintentos en este error en particular antes de darse por vencido).