2009-02-18 10 views
12

Ho un singolo processo che richiede una tabella per i record in cui PROCESS_IND = 'N', esegue qualche elaborazione e quindi aggiorna lo PROCESS_IND in 'Y'.Procedure ottimali per l'elaborazione multithread dei record di database

Mi piacerebbe consentire l'esecuzione di più istanze di questo processo, ma non so quali sono le migliori pratiche per evitare problemi di concorrenza.

Dove devo iniziare?

+0

può PROCESS_IND essere qualsiasi altro valore, ad esempio 'L'? – sfossen

+0

Certo, è utilizzato solo da questo processo, quindi può essere qualsiasi cosa –

+0

Inviare la dimensione della pagina, struttura della tabella, #rows e indici sarebbe di aiuto. – Vincent

risposta

9

Il modello che userei è la seguente:

  • creare colonne "lockedby" e "Locktime", che sono una discussione/processo/ID macchina e timestamp, rispettivamente (è necessario l'ID macchina quando di dividere l'elaborazione tra le diverse macchine)
  • Ogni compito sarebbe fare una ricerca del tipo:

    UPDATE taskstable SET lockedby = (il mio id), Locktime = ora() dove lockedby è ordine NULL BY ID LIMIT 10

Dove 10 è la "dimensione del lotto".

  • Poi ogni attività fa un SELECT per scoprire quale file è "bloccato" per la lavorazione, ed elabora quelli
  • Dopo ogni riga è completa, è possibile impostare lockedby e Locktime tornare a NULL
  • Tutto questo è fatto in un ciclo per tutti i lotti che esistono.
  • Un cron job, o attività pianificata, ripristina periodicamente il "lockedby" di qualsiasi riga il cui locktime è troppo tempo fa, come presumibilmente è stato fatto da un'attività che si è bloccata o si è bloccata. Qualcun altro li raccoglierà quindi

Il LIMIT 10 è specifico per MySQL ma penso che altri database abbiano equivalenti. L'ordine BY è importato per evitare che la query sia non deterministica.

+1

+1 per un'ottima idea. Semplicemente non so perché l'ORDINE BY sarebbe importante, a meno che non ci sia un ordine in cui le righe devono essere processate. Se è così, più processi sono comunque fuori discussione. – mghie

+0

In Sybase è possibile utilizzare "set rowcount {#rows | @variable}" per la dimensione batch equivalente a LIMIT. – Vincent

+0

L'ORDER BY è importante solo se hai bisogno che le tue istruzioni SQL siano deterministiche - in MySQL è importante riprodurre il log binario in modalità istruzione, che è vitale per la replica e il recupero point-in-time per funzionare. In altri database è meno cruciale. – MarkR

2

Si dovrebbe abilitare row level locking sul tavolo con:

CREATE TABLE mytable (...) LOCK DATAROWS 

Poi:

  • iniziare la transazione
  • Selezionare la riga con FOR UPDATE opzione (che bloccarlo)
  • Fai quello che vuoi.

Nessun altro processo può eseguire alcunché su questa riga fino al termine della transazione.

P. S. Alcuni menzionati problemi di sovraccarico che possono derivare dall'utilizzo di LOCK DATAROWS.

Sì, c'è un sovraccarico, anche se difficilmente lo chiamerei un problema per un tavolo come questo.

Ma se si passa alla DATAPAGES allora è possibile bloccare una sola riga per PAGE (2k di default), e processi il cui righe risiedono in una pagina non sarà in grado di eseguire contemporaneamente.

Se stiamo parlando di una tabella con decine di file bloccate in una sola volta, difficilmente si verificherà un calo notevole delle prestazioni.

La concorrenza del processo è molto più importante per un progetto del genere.

+0

Non conosciamo abbastanza informazioni per effettuare una chiamata su "tabella come questa", non conosciamo le dimensioni della pagina, quante righe per pagina, la dimensione della tabella o della struttura o quali altre query/processi sono sopra la tabella. Ho visto le app portate ai loro bisogni con l'implosione ben intenzionata delle serrature a livello di riga – Vincent

+0

Certo, non sappiamo nulla, ma facciamo un'ottimizzazione prematura, nel caso in cui :) – Quassnoi

+0

Non sono sicuro di cosa intendi? Passare immediatamente al blocco a livello di riga non è un'ottimizzazione prematura. Dovrebbe essere usato solo con parsimonia e di solito solo quando il codice non può essere modificato e ci sono deadlock che non possono essere risolti in altri modi. – Vincent

0

Convertire la procedura in una singola istruzione SQL ed elaborare più righe come un singolo batch. Questo è il modo in cui i database dovrebbero funzionare.

+0

Tuttavia, ci sono molti processi che non possono essere eseguiti nel DB. – you786

1

Il modo più ovvio è il blocco, se il database non ha blocchi, è possibile implementarlo da soli aggiungendo un campo "Bloccato".

Alcuni dei modi per semplificare la concorrenza è quello di randomizzare l'accesso agli articoli non elaborati, quindi, anziché la concorrenza sul primo elemento, distribuiscono l'accesso in modo casuale.

4

Sebbene comprenda l'intenzione, non sarei d'accordo sul passaggio a livello di riga immediatamente. Ciò ridurrà il tempo di risposta e potrebbe peggiorare la situazione. Se dopo aver provato si riscontrano problemi di concorrenza con APL, è necessario eseguire prima una mossa iterativa sul blocco "datapage"!

Per rispondere correttamente a questa domanda, sarebbero necessarie maggiori informazioni sulla struttura della tabella e sugli indici coinvolti, ma per spiegarlo meglio.

DOL, datarow locking utilizza molti più blocchi di blocco di tutte le pagine/pagine.Il sovraccarico nella gestione di tutti i blocchi e quindi la diminuzione della memoria disponibile a causa delle richieste di più strutture di blocco all'interno della cache ridurranno le prestazioni e neutralizzeranno i guadagni che potresti avere passando a un approccio più concorrente.

Testare il proprio approccio senza lo spostamento prima su APL (blocco di tutte le pagine 'predefinito'), quindi se vengono rilevati problemi, passare a DOL (prima il datapage e poi datarow). Tieni presente che quando passi da una tabella a DOL tutte le risposte su quella tabella diventano leggermente peggiori, la tabella utilizza più spazio e la tabella diventa più incline alla frammentazione che richiede una manutenzione regolare.

Quindi, in breve, non passare direttamente ai datarti, provare prima il proprio approccio di concorrenza, quindi se ci sono problemi, utilizzare il blocco dei datapage prima dei datarows di ultima istanza.