Servidor MySQL versión 5.1.41 con el complemento InnoDB habilitado. Tengo las siguientes tres tablas para facturas: facturas, componentes de factura y gastos de factura. Las facturas de tabla tienen la clave primaria invoice_id. Tanto invoice_components como invoice_expenses están vinculados a las facturas de la tabla con invoice_id como una foreign_key no única (cada factura puede tener más de un componente y más de un gasto). Ambas tablas tienen un índice BTREE para esta clave externa.InnoDB SELECT ... PARA la instrucción UPDATE que bloquea todas las filas en una tabla
que tienen las siguientes operaciones:
de transacción 1
START TRANSACTION;
SELECT * FROM invoices WHERE invoice_id = 18 FOR UPDATE;
SELECT * FROM invoice_components WHERE invoice = 18 FOR UPDATE;
SELECT * FROM invoice_expenses WHERE invoice = 18 FOR UPDATE;
Todo funciona bien para la primera transacción y las filas se seleccionan y se bloquea.
transacción 2
START TRANSACTION;
SELECT * FROM invoices WHERE invoice_id = 19 FOR UPDATE;
SELECT * FROM invoice_components WHERE invoice = 19 FOR UPDATE;
SELECT * FROM invoice_expenses WHERE invoice = 19 FOR UPDATE;
La segunda transacción vuelve ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
para la tercera consulta.
Lo mismo ocurre cuando trato de SELECCIONAR ... PARA ACTUALIZAR otras facturas y sus componentes y gastos. Parece que la primera transacción ha bloqueado todas las filas en la tabla invoice_expenses. ¿Alguna idea de por qué está pasando esto?
Otros detalles
Transacción 2 comienza después de la tercera consulta de transacción 1. No hay otros usuarios, las conexiones o las transacciones en el servidor.
El problema se produce en el nivel de aislamiento de transacción REPEATABLE READ predeterminado. Se soluciona al cambiar al nivel LECTURA COMPROMETIDA. Esta es una solución, pero aún no explica por qué el problema está ocurriendo con fact_expenses y no con fact_components.
¿Estás seguro de que todos los registros están bloqueados? InnoDB puede bloquear los registros del vecindario (cuando se bloquean 18 - 17 y 19 también), pero no debe bloquear los registros que están muy lejos en el btree - así que intente esto con una mayor distancia en los identificadores. Además, ¿cuál es su nivel de aislamiento? –
@Darhazer. Gracias. Cambiar el nivel de aislamiento a READ COMMITTED resolvió el problema. ¿Puedes explicar lo que estaba pasando? ¿El espaciado MySQL estaba bloqueando mi tabla invoice_expenses? ¿Por qué no sucedió lo mismo con invoice_components? De cualquier manera, si publica una respuesta lo aceptaré. –
No tengo respuesta por qué esto está sucediendo en READATABLE READ, así que preferiría ponerle una recompensa a la pregunta, que publicar una respuesta incompleta. ¿Esas son las únicas consultas que se ejecutan en las transacciones? ¿Se inicia la segunda transacción después de realizar la tercera consulta en la primera transacción, o son concurrentes? Agregaré una recompensa después de los 2 días requeridos por SO –