2012-03-30 16 views
11

Necesito hacer que el servidor MySQL revertir la transacción inmediatamente después de que su cliente se desconectó, porque cada cliente funciona al mismo tiempo. El problema se puede reproducir como estos (utilizando un tipo de tabla InnoDB)

El Cliente A:Retroceso de MySQL en la transacción con la conexión perdida/desconectada

START TRANSACTION; 
SELECT MAX(ID) FROM tblone FOR UPDATE; 
#... then disconnect your connection to the server 

El Cliente B:

START TRANSACTION; 
SELECT MAX(ID) FROM tblone FOR UPDATE; 
#... lock wait time out will occur here 

me había propuesto opción de servidor de MySQL como innodb_rollback_on_timeout y el uso cliente de mysql mysql --skip-reconnect en ambos clientes. Intenté esto usando un servidor y dos clientes en una red. Desconecté físicamente la red (desconecto el cable) después de la línea SELECT ... FOR UPDATE;. Necesito hacer que otros clientes puedan usar el tblone en una transacción (bloquearlo, actualizarlo) inmediatamente, y para que eso suceda, creo que el servidor debería revertir la transacción para el Cliente A, después de que el Cliente A se desconecte.

+0

Interesante pregunta. ¡Pensé que esto es automático! Entonces necesitamos algo como 'innodb_rollback_on_disconnect' .. eso sería genial y yo diría, ¡ese debería ser el predeterminado! Esa sería una solicitud de cambio razonable para mysql. – TMS

Respuesta

10

Cuando desconecta físicamente un cliente no está enviando una desconexión normal (lo que hubiera provocado una reversión) y el protocolo MySQL no es muy hablador por lo que el servidor nunca sabe que el cliente no está allí. Creo que esto es un defecto en el protocolo al compararlo con otros sistemas de bases de datos donde el cliente y el servidor hablan internamente mucho más.

De todos modos. Hay dos variables que puedes cambiar. Básicamente hacen lo mismo pero para diferentes clientes.

El primero es wait_timeout y lo utilizan clientes de aplicaciones como java o php.

El otro es interactive_timeout y que es utilizado por el cliente mysql (como en las pruebas)

En ambos casos el servidor para mata la conexión después de un número de segundos y al hacerlo Rollbacks todas las transacciones y libera todos cabellos.

+0

Gracias por su respuesta, y he intentado usar ambas opciones, y configurarlas en 60 segundos (para experimentar), pero surge otro problema. Después de 60 segundos de inactividad (inactividad), la conexión se cerró automáticamente y la siguiente consulta produjo un error (el servidor se fue) y luego se volvió a conectar automáticamente. ¿Debo codificar algo para consultar cada 59 para asegurarme de que la conexión está activa? ¿O hay otra manera? ¿Una consulta larga que toma más de 60 se desconectará en el medio del proceso? – qsoft

+0

Como solo necesito este comportamiento durante la transacción, ¿puedo hacer algo como 'SET SESSION wait_timeout = 60' justo antes de la transacción y restaurarlo después de una confirmación/restitución? – qsoft

+0

Debería poder cambiarlo dentro de su procedimiento almacenado o como una declaración separada antes de comenzar una transacción. Y tiene razón cuando se cierra la conexión inactiva. Así es como funciona. Sin embargo, las consultas de larga ejecución no cuentan como "inactivas" por lo que he visto, así que deberían ser seguras (fácil de probar con 'select 1, sleep (61) from dual') –

Cuestiones relacionadas