2010-03-22 17 views
7

preliminari:MySQL: Operazioni su più fili

Ho un'applicazione che mantiene un pool di thread di circa 100 fili. Ogni thread può durare circa 1-30 secondi prima che una nuova attività lo sostituisca. Quando finisce un thread, quel thread risulterà quasi sempre nell'inserimento di 1-3 record in una tabella, questa tabella viene utilizzata da tutti i thread. Al momento, non esiste alcun supporto transazionale, ma sto cercando di aggiungerlo ora. Inoltre, la tabella in questione è InnoDB. Quindi ...

Goal

Voglio realizzare una transazione per questo. Le regole per l'esecuzione o il rollback di questa transazione risiedono nel thread principale. Fondamentalmente esiste una semplice funzione che restituirà un valore booleano.

  1. Posso implementare una transazione su più connessioni?
  2. In caso contrario, più thread possono condividere la stessa connessione? (Nota: ci sono molti inserti in corso qui, e questo è un requisito).

risposta

3

Bene, come indicato in una risposta diversa non è possibile creare una transazione su più connessioni. E puoi condividere la singola connessione tra thread. Tuttavia, con devi stare molto attento. È necessario assicurarsi che solo un thread stia scrivendo alla connessione contemporaneamente. Non è possibile avere più thread che parlano attraverso la stessa connessione senza sincronizzare le loro attività in qualche modo. Probabilmente accadranno cose brutte se permetti a due thread di parlare contemporaneamente (corruzioni della memoria nella libreria client, ecc.). Usare una mutex o una sezione critica per proteggere le conversazioni di connessione è probabilmente la strada da percorrere.

-Don

+0

Forse, penso che potrei ripensare a questo semplicemente facendo in modo che il thread aspetti il ​​test del thread principale da completare prima di eseguire il commit. – Zombies

+0

Solo un pensiero, non l'ho verificato: se crei le tue funzioni 'start_transaction()' e 'commit()'/'rollback()' e blocchi un mutex in 'start_transaction()' e lo sblocchi sulla transazione fine, le transazioni saranno molto più sicure da utilizzare nei thread. Non dico che funzionerà come da una connessione diversa. Solo a volte inizi le transazioni in thread e fai affidamento su di esse per essere atomiche. Si noti inoltre che mysql sais che solo una query alla volta dovrebbe essere in esecuzione all'interno di tutti i thread. Ciò include dall'esecuzione della query per completare il recupero del risultato. – NickSoft

+0

La comunicazione sulla connessione deve essere serializzata. Un approccio consiste nell'avere un thread di comunicazione dedicato e fare in modo che altri thread facciano tutto il lavoro necessario, quindi passare i risultati al thread di comunicazione, che serializza le istruzioni. –

4

1) No, una transazione è limitata a una singola connessione DB.

2) Sì, una connessione (e una transazione) può essere condivisa su più thread.

+0

quanto riguarda (2), e se la tabella è INNODB, prendo che è sicuro di avere più inserti verificano contemporaneamente? – Zombies

+0

@Zombies Sì, anche se non ho esperienza con InnoDB e Transactions, credo che dovrebbe andare bene. Non vedo ragioni per cui non funzioni. –

0

La condivisione delle connessioni tra molti thread viene in genere implementata utilizzando un pool di connessioni. Ogni thread può richiedere una connessione dal pool, utilizzarlo per i suoi scopi (una o più transazioni, commit o rollback) e restituirlo al pool una volta che l'attività è terminata.

Questo è ciò che i server delle applicazioni offrono. Si prenderanno cura delle transazioni, anche io. e. quando il metodo che ha richiesto la transazione termina normalmente, le modifiche vengono confermate, se genera un'eccezione, la transazione del database viene annullata.

Suggerisco di dare un'occhiata a Java EE 5 o 6 - è molto facile da usare e può anche essere impiegato in sistemi embedded. Per iniziare in modo semplice, dai un'occhiata a Netbeans e al server di applicazioni Glassfish. Tuttavia, i concetti generali si applicano a tutti i server delle applicazioni allo stesso modo.

Per quanto riguarda InnoDB, non avrà problemi a gestire molte transazioni. Sotto la supervisione del server delle app, puoi concentrarti sulla logica di business e non devi preoccuparti di aggiornamenti semigrafici o di chiunque veda aggiornamenti/inserti prima che la transazione da cui provengono sia stata commessa.

InnoDB utilizza MVCC (controllo della concorrenza a più versioni), presentando efficacemente ogni transazione con un'istantanea dell'intero database a partire dal momento in cui è stata avviata. Puoi leggere ulteriori informazioni su MVCC qui in una domanda correlata: Question 812512

+0

Questo non verrà implementato su J2EE. Ma in futuro utilizzerà un pool di connessioni J2SE sì. Quindi prendo il fatto che posso eseguire il rollback su tutte le connessioni nel pool di connessioni ...? – Zombies

+0

Sì, MVCC imposta automaticamente un livello di isolamento della transazione di "lettura ripetibile", nel senso che una volta che una transazione ha letto il primo bit di dati, non vedrà alcun aggiornamento da altre transazioni, anche se vengono commesse. Solo quando la transazione corrente viene impegnata o ripristinata, la prossima transazione su questa connessione vedrà i nuovi dati da tutti gli altri che si sono impegnati fino a quel momento. –

+0

Giusto per essere chiari: non sarà possibile emettere un unico comando "rollback tutte le transazioni aperte". Ma di solito non è quello che vorresti comunque - se è così, penso che tu abbia bisogno di gettare più luce sul tuo sistema, perché non sembrerebbe giusto. –