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 UPDATEcomo 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_timeoutvariable 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
ROLLBACKsi 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_timeoutointeractive_timeoutmediados de transacción, la transacción se deshace? ¿Hay alguna forma de probar esto desde la consola?
Aclaración : innodb_lock_wait_timeoutestablece 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_timeoutno 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 UPDATEantes de la SLEEPlínea, luego inicia una segunda transacción desde otro cliente que intenta en SELECT ... FOR UPDATEla 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.
ROLLBACKen la primera transacción si tarda más de nsegundos en completarse. ¿Hay alguna manera de hacerlo?
MYSQLtiene 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.