2009-08-20 10 views
9

Tenemos una mesa (en la actualidad InnoDB), que contiene aproximadamente 500.000 filas. Esto representa una cola de tareas para ejecutar. Se almacena en una base de datos MySQL.interbloqueos en MySQL filas eliminación

Una forma continua, al menos una vez por segundo, pero a veces con más frecuencia, seleccionamos los datos de ella y posteriormente actualizar algunas filas. Una vez por día, podamos filas antiguas de la tabla.

empezamos a recibir los puntos muertos sobre la mesa y esto trajo nuestra procesamiento de tareas a un punto muerto. Estos bloqueos se produjeron durante la corrida de ciruela nocturna. La combinación de DELETE, SELECT y UPDATE significó que esencialmente nada productivo podría suceder. Desafortunadamente no tengo la salida de un SHOW ENGINE INNODB STATUS.

Me gustaría saber la mejor opción para tratar con esto. Tenga en cuenta que nuestro código detecta interbloqueos y vuelve a enviar la consulta. Además, hace tiempo descubrimos que eliminar todas las filas coincidentes a la vez era demasiado exigente en una tabla de base de datos que mostraba mucha actividad, por lo que LIMITAMOS nuestras eliminaciones a 10.000 filas a la vez y seguimos volviendo a enviar la consulta hasta que se hayan completado todas las filas necesarias podado

veo las siguientes opciones, y nos gustaría comentarios sobre cuáles son las mejores, o sugerencias para otras opciones:

  1. Eliminar un menor número de filas a la vez
  2. Uso retroceso exponencial en nuestros eliminaciones, aunque yo a mí respecta
  3. LOCK TABLES que esto no ayuda dada nuestra carga de trabajo específica como por MySQL documentation. Probablemente podríamos aceptar el bloqueo de las instrucciones SELECT y UPDATE durante la duración de las eliminaciones.
  4. Cambie al tipo de tabla MyISAM. Fuimos con InnoDB porque inicialmente estábamos usando transacciones en esta tabla. Este ya no es el caso. No estoy lo suficientemente familiarizado con los detalles para saber si esta es una solución viable.
  5. quizás al uso LOW_PRIORITY UPDATE. Puede ser que los DELETE no afecten a los SELECT, solo a las ACTUALIZACIONES, y esto puede ser suficiente.
+1

Todos los interbloqueos que he encontrado se deben a transacciones no confirmadas. Asegúrese de que está ejecutando correctamente las transacciones (ya sea con confirmación automática activada o confirmación automática desactivada y la gestión real de confirmaciones/reversiones). – localshred

+0

Definitivamente es un buen punto; este sería el caso la mayor parte del tiempo, pero en realidad no estamos haciendo transacciones en esta mesa. Solíamos, pero ya no hacemos. – ChrisInEdmonton

Respuesta

4

Al realizar operaciones DML, InnoDB cerraduras todas las filas escaneadas, no coincidentes.

consideran este diseño de la mesa:

DROP TABLE t_tran; 

CREATE TABLE t_tran (id INT NOT NULL PRIMARY KEY, data INT NOT NULL, KEY ix_tran_data (data)) Engine=InnoDB; 

DROP TABLE t_tran; 

CREATE TABLE t_tran (id INT NOT NULL PRIMARY KEY, data INT NOT NULL, KEY ix_tran_data (data)) Engine=InnoDB; 

INSERT 
INTO t_tran 
VALUES 
(1, 1), 
(2, 2), 
(3, 3), 
(4, 4), 
(5, 5), 
(6, 6), 
(7, 7), 
(8, 8); 

START TRANSACTION; 

DELETE 
FROM t_tran 
WHERE data = 2 
     AND id <= 5; 

En este caso, MySQL selecciona RANGE ruta de acceso en id, que considera más barato que REF en data.

En una operación simultánea, usted será capaz de eliminar o actualizar filas 6, 7, pero no 8 filas 1-5 ya que están bloqueados (a pesar del hecho de que sólo la fila 2 se vio afectada).

Si elimina id <= 5 de la condición anterior, podrá eliminar cualquier fila, excepto la fila 3.

Lamentablemente, no puede controlar las rutas de acceso MySQL en las operaciones DML.

Lo mejor que puede hacer es indexar sus condiciones correctamente y esperar que MySQL seleccione estos índices.

+0

Gracias, nosotros (mi administrador de sistemas y yo) somos de la opinión de que esta es probablemente la mejor solución. También hemos reducido la cantidad de eliminación y agregado de retroceso exponencial. Veremos si eso soluciona el problema. – ChrisInEdmonton

1

Asegúrese de que el aislamiento de su transacción esté marcado como lectura confirmada y no repetible. Read commited debería ser el predeterminado, pero vimos que en nuestro servidor el valor predeterminado de innodb era de lectura repetible.

Puede comprobar ejecutando el siguiente:

SHOW VARIABLES LIKE 'tx%'; 

Para establecer esto, en el archivo my.cnf entrar en la línea folloiwing:

tx_isolation=READ-COMMITTED 
Cuestiones relacionadas