Aiuto con fili java o esecutori: L'esecuzione di diversi MySQL seleziona, inserimenti e aggiornamenti simmultaneously

StackOverflow https://stackoverflow.com/questions/2953955

Domanda

Sto scrivendo un'applicazione per analizzare un database MySQL, e ho bisogno di eseguire più LMD simmultaneously; per esempio:

// In ResultSet rsA: Select * from A;
rsA.beforeFirst();
while (rsA.next()) {
   id = rsA.getInt("id");
   // Retrieve data from table B: Select * from B where B.Id=" + id;
   // Crunch some numbers using the data from B
   // Close resultset B
}

sto dichiarando un array di oggetti di dati, ognuno con la propria connessione al database, che a sua volta chiama diversi metodi per l'analisi dei dati. Il problema è tutte le discussioni utilizzano la stessa connessione, in tal modo tutte le attività gettano exceptios: "Blocco di timeout di attesa superato; provare a riavviare transazione"

Credo che ci sia un modo per scrivere il codice in modo tale che un qualsiasi oggetto ha una propria connessione ed esegue i compiti richiesti indipendenti da qualsiasi altro oggetto. Ad esempio:

DataObject dataObject[0] = new DataObject(id[0]);
DataObject dataObject[1] = new DataObject(id[1]);
DataObject dataObject[2] = new DataObject(id[2]);
...
DataObject dataObject[N] = new DataObject(id[N]);
// The 'DataObject' class has its own connection to the database, 
// so each instance of the object should use its own connection. 
// It also has a "run" method, which contains all the tasks required.
Executor ex = Executors.newFixedThreadPool(10);

for(i=0;i<=N;i++) {
   ex.execute(dataObject[i]);
}
// Here where the problem is: Each instance creates a new connection,
// but every DML from any of the objects is cluttered in just one connection
// (in MySQL command line, "SHOW PROCESSLIST;" throws every connection, and all but
// one are idle).

Mi può puntare nella direzione giusta?

Grazie

È stato utile?

Soluzione 2

Dopo un certo tempo di rottura del cervello, ho capito i miei errori ... Voglio mettere questa nuova conoscenza, così ... qui vado

Ho fatto un grande errore dichiarando l'objet Connection come un oggetto statico nel mio codice ... così ovviamente, nonostante ho creato una nuova connessione per ogni nuovo oggetto di dati che ho creato, tutte le transazioni ha attraversato un singolo, statica, connessione.

Con questo primo numero corretto, sono tornato al tavolo di progettazione, e si rese conto che il mio processo è stato:

  1. Leggi un ID da una tabella di input
  2. Prendere un blocco di dati relativi alla Id leggere al punto 1, memorizzato in altre tabelle di input
  3. numeri Crunch: Leggere le tabelle di input ed elaborare i dati memorizzati in essi
  4. Salva i risultati in una o più tabelle di output
  5. Ripeti il ??processo mentre ho in attesa Ids nella tabella di input

semplicemente utilizzando una connessione dedicata per la lettura di ingresso e di una connessione dedicata per la scrittura di uscita, le prestazioni del mio programma è aumentata ... ma avevo bisogno di molto di più!

Il mio approccio originale per i punti 3 e 4 era di salvare in uscita ogni uno dei risultati non appena li ho avuto ... ma ho trovato un approccio migliore:

  • Leggi i dati di input
  • Crunch i numeri, e inserire i risultati in un gruppo di code (uno per ogni tabella di output)
  • Un filo separato sta controllando ogni secondo se c'è dati in una qualsiasi delle code. Se ci sono dati nelle code, scriverlo ai tavoli.

Quindi, dividendo operazioni di immissione e di uscita usando connessioni diverse, e reindirizzando l'output processo fondamentale di una coda, e utilizzando un filo dedicato per attività di storage uscita, finalmente ottenuto ciò che volevo: L'esecuzione di Multithreaded DML


So che ci sono meglio approcci a questo particolare problema, ma questo funziona abbastanza bene.

Quindi ... se qualcuno è bloccato con un problema come questo ... Spero che questo aiuta.

Altri suggerimenti

Credo che il problema è che hai confusi un sacco di livello intermedio, transazionale, e la logica persistente in una classe.

Se hai a che fare direttamente con ResultSet, non stai a pensare alle cose in un modo molto orientata agli oggetti.

Sei intelligente, se si riesce a capire come ottenere il database per fare un po 'di calcoli.

In caso contrario, mi consiglia mantenere connessioni aperte per il tempo minimo possibile. Aprire una connessione, ottenere il ResultSet, la mappa in una struttura di oggetto o di dati, chiudere il ResultSet e collegamento in ambito locale, e restituire il / struttura dati mappati oggetto per l'elaborazione.

È mantenere la persistenza e la logica di elaborazione separano in questo modo. Tu stesso risparmiare un sacco di dolore, mantenendo connessioni di breve durata.

Se una soluzione stored procedure è lento potrebbe essere dovuto alla scarsa indicizzazione. Un'altra soluzione si esibirà altrettanto male, se non peggio. Provare a eseguire SPIEGARE PLAN e vedere se tutte le vostre domande utilizzano tabella di scansione. Se sì, si dispone di alcuni indici da aggiungere. Potrebbe anche essere causa di grossi tronchi di rollback se le tue transazioni sono di lunga durata. C'è un sacco si potrebbe e dovrebbe fare per garantire che hai fatto tutto il possibile con la soluzione che avete prima di commutazione. Si potrebbe andare a una grande quantità di sforzo e ancora non affrontare la causa principale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top