Esto surgió de esta pregunta relacionada , donde quería saber cómo forzar que dos transacciones ocurrieran secuencialmente en un caso trivial (donde ambas operan en una sola fila). Obtuve una respuesta, usar SELECT ... FOR UPDATE
como la primera línea de ambas transacciones, pero esto lleva a un problema: si la primera transacción nunca se confirma o revierte, la segunda transacción se bloqueará indefinidamente. La innodb_lock_wait_timeout
variable establece el número de segundos después de los cuales el cliente que intenta hacer la segunda transacción se le dice "Lo siento, inténtelo de nuevo" ... pero hasta donde puedo decir, lo intentarían nuevamente hasta el próximo reinicio del servidor. Entonces:
- ¿Seguramente debe haber una manera de forzar un
ROLLBACK
si una transacción está tomando para siempre? ¿Debo recurrir al uso de un demonio para matar tales transacciones, y si es así, cómo sería ese demonio? - Si la conexión es matado por
wait_timeout
ointeractive_timeout
mediados de transacción, la transacción se deshace? ¿Hay alguna forma de probar esto desde la consola?
Aclaración : innodb_lock_wait_timeout
establece el número de segundos que una transacción esperará a que se libere un bloqueo antes de darse por vencido; lo que quiero es una forma de forzar la liberación de un bloqueo.
Actualización 1 : Aquí hay un ejemplo simple que demuestra por qué innodb_lock_wait_timeout
no es suficiente para garantizar que la segunda transacción no esté bloqueada por la primera:
START TRANSACTION;
SELECT SLEEP(55);
COMMIT;
Con la configuración predeterminada de innodb_lock_wait_timeout = 50
, esta transacción se completa sin errores después de 55 segundos. Y si agrega un UPDATE
antes de la SLEEP
línea, luego inicia una segunda transacción desde otro cliente que intenta en SELECT ... FOR UPDATE
la misma fila, es la segunda transacción que agota el tiempo de espera, no la que se durmió.
Lo que estoy buscando es una forma de forzar el final del sueño reparador de esta transacción.
Actualización 2 : en respuesta a las preocupaciones de hobodave sobre cuán realista es el ejemplo anterior, aquí hay un escenario alternativo: un DBA se conecta a un servidor en vivo y se ejecuta
START TRANSACTION
SELECT ... FOR UPDATE
donde la segunda línea bloquea una fila en la que la aplicación escribe con frecuencia. Luego, el DBA se interrumpe y se va, olvidando finalizar la transacción. La aplicación se detiene hasta que se desbloquea la fila. Me gustaría minimizar el tiempo que la aplicación está atascada como resultado de este error.
ROLLBACK
en la primera transacción si tarda más de n
segundos en completarse. ¿Hay alguna manera de hacerlo?
MYSQL
tiene una configuración para evitar este escenario. Porque no es aceptable que el servidor se cuelgue debido a la irresponsabilidad de los clientes. No encontré ninguna dificultad para entender su pregunta, también es tan relevante.