2013-01-17 8 views
6

Ho bisogno di un piccolo aiuto con SELECT FOR UPDATE (resp. LOCK IN SHARE MODE).SELECT ... FOR UPDATE da una tabella in più thread

Ho una tabella con circa 400 000 record e ho bisogno di eseguire due diverse funzioni di elaborazione su ogni riga.

La struttura della tabella è appropriatamente questo:

data (
    `id`, 
    `mtime`, -- When was data1 set last 
    `data1`, 
    `data2` DEFAULT NULL, 
    `priority1`, 
    `priority2`, 
    PRIMARY KEY `id`, 
    INDEX (`mtime`), 
    FOREIGN KEY ON `data2` 
) 

Le funzioni sono un po 'diverso:

  • prima funzione - ha per l'esecuzione in loop su tutti i record (è abbastanza veloce), dovrebbe selezionare i record basati su priority1; imposta data1 e mtime
  • seconda funzione - deve essere eseguito solo una volta su ogni record (è piuttosto lento), dovrebbe selezionare i record in base a priority2; imposta data1 e mtime

Non dovrebbero modificare la stessa riga, allo stesso tempo, ma il ristretto, può restituire una riga in entrambi (priority1 e priority2 hanno valori diversi) e va bene per la transazione di aspettare se questo è il caso (e mi aspetterei che questo sarebbe l'unico caso in cui bloccherà).

sto selezionando i dati basati su query seguenti:

-- For the first function - not processed first, then the oldest, 
-- the same age goes based on priority 
SELECT id FROM data ORDER BY mtime IS NULL DESC, mtime, priority1 LIMIT 250 FOR UPDATE; 

-- For the second function - only processed not processed order by priority 
SELECT if FROM data ORDER BY priority2 WHERE data2 IS NULL LIMIT 50 FOR UPDATE; 

Ma quello che sto vivendo è che ogni volta una sola query restituisce al momento.

Quindi le mie domande sono:

  • È possibile acquisire due serrature separate in due operazioni distinte sul mazzo separata di righe (nella stessa tabella)?
  • Ho molte collisioni tra la prima e la seconda query (ho problemi nel debugging, qualsiasi suggerimento su come eseguire il debug di SELECT ... FROM (SELECT ...) WHERE ... IN (SELECT) sarebbe apprezzato)?
  • Can ORDER BY ... LIMIT ... può causare problemi?
  • Gli indici e le chiavi possono causare problemi?
+0

cosa è il tipo di tabella? MyISAM o InnoDB? Per quanto ne so, solo InnoDB ha il blocco a livello di riga. MyISAM ha solo un blocco a livello di tabella. –

+0

Vedo ... Hai qualche indice sul tuo tavolo? –

+0

@ Mt.Schneiders Sì, sì. Li ho aggiunti allo schema. Grazie per averlo notato. – Vyktor

risposta

3

cose chiave da controllare per la prima di ottenere molto di più:

  • assicurare che il motore tabella è InnoDB, altrimenti "per l'aggiornamento" non ha intenzione di bloccare la fila, come non ci saranno le transazioni.
  • Assicurati di utilizzare correttamente la funzione "per l'aggiornamento". Se selezioni qualcosa per l'aggiornamento, è bloccato su quella transazione. Mentre altre transazioni possono essere in grado di leggere la riga, non può essere selezionata per l'aggiornamento, l'aggiornamento o l'eliminazione da parte di un'altra transazione finché il blocco non viene rilasciato dalla transazione di blocco originale.
  • Per mantenere le cose pulite, provare ad avviare una transazione in modo esplicito utilizzando "START TRANSACTION", eseguire la selezione "per aggiornamento", fare tutto ciò che si intende fare nei record restituiti e terminare eseguendo esplicitamente un "COMMIT" per chiudere la transazione.

Ordine e limite non avrà alcun impatto sul problema riscontrato per quanto posso dire, tutto ciò che stava per essere restituito dal Select saranno le righe che vengono bloccati.

per rispondere alle vostre domande:

  1. È possibile acquisire due serrature separate in due operazioni distinte sul mazzo separata di righe (nella stessa tabella)?
    Sì, ma non sulle stesse righe. I blocchi possono esistere solo a livello di riga in una transazione alla volta.
  2. Ho molte collisioni tra prima e seconda query (ho problemi di debugging, qualsiasi suggerimento su come eseguire il debug SELECT ... FROM (SELECT ...) WHERE ... IN (SELECT) sarebbe apprezzato) ?
    Potrebbe esserci un breve periodo in cui viene calcolato il blocco riga, che ritarderà la seconda query, tuttavia, a meno che non si stiano eseguendo molte centinaia di questi selezionare per gli aggiornamenti in una volta, non dovrebbe causare alcun significativo o notevole ritardi.
  3. È possibile ORDINARE PER ... LIMIT ... causa problemi? Non nella mia esperienza. Dovrebbero funzionare come sempre su una normale istruzione select.
  4. Gli indici e le chiavi possono causare problemi?
    Gli indici devono sempre esistere per garantire prestazioni sufficienti, ma non dovrebbero causare problemi con l'ottenimento di un blocco.
0

Tutti i punti in risposta accettata sembrano bene, tranne sotto dei 2 punti: "tutto ciò stava per essere restituito dal Select saranno le righe che vengono bloccati." & "Può indici e chiavi causare problemi? ma non dovrebbe causare problemi con l'ottenimento di una serratura."

invece tutte le righe che vengono lette internamente da DB durante decidere quali righe da selezionare e ritorno sarà bloccato Ad esempio qui sotto la query bloccherà tutte le righe della tabella ma potrebbe selezionare e restituire solo poche righe: seleziona * dalla tabella dove non_primary_non_indexed_column =? per l'aggiornamento Poiché non esiste un indice, DB dovrà leggere l'intera tabella per cercare la riga desiderata e quindi bloccare l'intera tabella.

Se si desidera bloccare solo una riga, è necessario specificare la sua chiave primaria o una colonna indicizzata nella clausola where. Pertanto l'indicizzazione diventa molto importante in caso di blocco solo delle righe appropriate.

Questo è un buon riferimento - https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

Problemi correlati