2012-03-30 18 views
11

Ho bisogno di rendere il server MySQL per la transazione di rollback immediatamente dopo che il client è disconnesso, perché ogni client funziona in modo concorrente. Il problema può essere riprodotto come questi (utilizzando un tipo InnoDB tabella)

Su client A:Rollback MySQL su transazione con connessione persa/disconnessa

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

Sul client B:

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

avevo impostato opzione server di MySQL come innodb_rollback_on_timeout e l'utilizzo client di mysql mysql --skip-reconnect su entrambi i client. Ho provato questo utilizzando un server e due client, su una rete. Ho disconnesso fisicamente la rete (scollega il cavo) dopo la linea SELECT ... FOR UPDATE;. Devo fare in modo che altri client siano in grado di utilizzare tblone su una transazione (bloccarlo, aggiornarlo) immediatamente e, poiché ciò accade, penso che il server debba eseguire il rollback della transazione per il client A, dopo che il client A si disconnette.

+0

Interessante domanda. Ho pensato che fosse automatico! Quindi abbiamo bisogno di qualcosa come "innodb_rollback_on_disconnect' .. sarebbe fantastico e direi che dovrebbe essere l'impostazione predefinita! Sarebbe una ragionevole richiesta di modifica per mysql. – TMS

risposta

10

Quando disconnetti fisicamente un client non invii una normale disconnessione (che avrebbe causato un rollback) e il protocollo MySQL non è molto chiacchierone, quindi il server non sa mai che il client non è presente. Penso che questo sia un difetto nel protocollo quando si confronta con altri sistemi di database in cui il client e il server parlano internamente molto di più.

In ogni caso. Ci sono due variabili che potresti cambiare. Fondamentalmente fanno lo stesso, ma per clienti diversi.

Il primo è ed è utilizzato dai client delle applicazioni come java o php.

L'altro è interactive_timeout ed è utilizzato dal cliente mysql (come nei test)

In entrambi i casi il server per uccide la connessione dopo un certo numero di secondi e quando farlo rollback tutte le transazioni e rilasci tutti serrature.

+0

Grazie per la risposta, e ho provato a utilizzare entrambe le opzioni e impostarle su 60 secondi (per l'esperimento), ma sorge un altro problema. Dopo 60 secondi di inattività (inattiva), la connessione si è chiusa automaticamente e la query successiva ha generato un errore (il server è andato via) e quindi si riconnette automaticamente. Devo codificare qualcosa per interrogare ogni 59s per verificare che la connessione sia attiva? oppure c'è un'altro modo? Una lunga query che impiega più di 60 si disconnetterà nel bel mezzo del processo? – qsoft

+0

Perché ho bisogno di questo comportamento solo durante la transazione, posso fare qualcosa come "SET SESSION wait_timeout = 60' appena prima della transazione e ripristinarlo dopo un commit/rollback? – qsoft

+0

Dovresti poterlo modificare all'interno della stored procedure o come istruzione separata prima di iniziare una transazione. E hai ragione quando la connessione inattiva viene chiusa. Ecco come funziona. Tuttavia, le query di lunga durata non contano come "idle" per quanto ho visto, quindi dovrebbero essere sicure (facile da testare con 'selezionare 1, sleep (61) da dual') –