Effetti della concorrenza

Le operazioni di modifica dei dati eseguite da un utente possono influire sulle operazioni di lettura o modifica degli stessi dati eseguite contemporaneamente da altri utenti. Tale fenomeno è denominato accesso simultaneo ai dati. Se il sistema di archiviazione dati non dispone di controllo della concorrenza, gli utenti potrebbero riscontrare gli effetti collaterali seguenti:

  • Perdita di aggiornamenti

  • Dipendenza di cui non è stato eseguito il commit (lettura dirty).

  • Analisi inconsistente (lettura non ripetibile)

  • Lettura di righe fantasma

  • Letture di righe mancanti e doppie provocate dagli aggiornamenti della riga

Perdita di aggiornamenti

Il problema della perdita degli aggiornamenti si verifica quando due o più transazioni selezionano la stessa riga, la quale viene quindi aggiornata in base al valore selezionato inizialmente. Ogni transazione non è, infatti, a conoscenza dell'esecuzione delle altre transazioni. L'ultimo aggiornamento pertanto sovrascrive quelli eseguiti in precedenza dalle altre transazioni, con conseguente perdita di dati.

Si supponga, ad esempio, che due revisori creino una copia in formato elettronico del medesimo documento e successivamente modifichino e salvino la propria copia del documento. Con questa operazione la copia originale del documento viene sovrascritta e l'ultimo revisore che esegue il salvataggio sovrascrive la copia modificata dall'altro revisore. Questo problema potrebbe essere evitato impedendo a un revisore di accedere al file finché l'altro non abbia completato l'operazione ed eseguito il commit della transazione.

Dipendenza uncommitted (lettura dirty)

La dipendenza uncommitted si verifica quando una transazione seleziona una riga mentre questa viene aggiornata da un'altra transazione. La seconda transazione legge i dati di cui non è ancora stato eseguito il commit, i quali potrebbero venire modificati dalla transazione che sta eseguendo l'aggiornamento della riga.

Si supponga, ad esempio, che un revisore stia modificando un documento in formato elettronico e che un secondo revisore apra una copia del documento contenente tutte le modifiche apportate fino a quel momento e lo distribuisca ai destinatari del documento. Si supponga inoltre che il primo revisore decida di eliminare le modifiche apportate e quindi salvi il documento. In questo caso, il documento distribuito contiene modifiche non più esistenti e quindi da considerare come non più valide. Questo problema potrebbe essere evitato impedendo a tutti gli utenti di leggere il documento modificato fino a quando il primo revisore non salva definitivamente le modifiche ed esegue il commit della transazione.

Analisi inconsistente (lettura non ripetibile)

L'analisi inconsistente si verifica quando una transazione accede più volte alla stessa riga e legge ogni volta dati diversi. Questo problema è molto simile alla dipendenza uncommitted, in quanto una transazione modifica i dati che una seconda transazione sta leggendo. Nel caso dell'analisi inconsistente, tuttavia, la transazione di modifica ha già eseguito il commit dei dati letti dalla transazione di lettura. Con l'analisi inconsistente vengono, inoltre, eseguite due o più operazioni di lettura della stessa riga e a ogni lettura le informazioni vengono modificate da un'altra transazione. Da ciò deriva il termine lettura non ripetibile.

Si supponga, ad esempio, che un revisore legga lo stesso documento due volte e che nell'intervallo tra la prima e la seconda lettura l'autore del documento apporti alcune modifiche. Quando il revisore legge il documento la seconda volta, il testo risulta diverso, ovvero la lettura originale non è ripetibile. Questo problema potrebbe essere evitato impedendo all'autore di modificare il documento fino a quando il revisore non ha completato l'ultima lettura.

Lettura di righe fantasma

Le righe fantasma si verificano quando viene eseguita un'operazione di inserimento o eliminazione di una riga inclusa in un intervallo di righe lette da una transazione. Alla prima lettura dell'intervallo di righe viene visualizzata una riga che, in seguito all'eliminazione eseguita da una transazione diversa, non sarà più disponibile nelle successive letture. In modo analogo, alla lettura successiva a un'operazione di inserimento eseguita da una transazione diversa, viene visualizzata una riga non inclusa nella lettura precedente.

Si supponga, ad esempio, che un revisore modifichi un documento che gli è stato consegnato dall'autore e che, in fase di implementazione delle modifiche nella copia principale del documento, si scopra che l'autore ha inserito nel documento parti aggiuntive non riviste. Come nel caso della lettura non ripetibile, è possibile evitare questo problema impedendo a tutti gli altri utenti di aggiungere nuove parti a un documento fino a quando il revisore non ha completato il proprio lavoro sul documento originale.

Letture di righe mancanti e doppie provocate dagli aggiornamenti della riga

  • Riga aggiornata mancante o più visualizzazioni di una riga aggiornata

    Le transazioni eseguite al livello READ UNCOMMITTED non acquisiscono blocchi condivisi per evitare che altre transazioni possano modificare i dati letti dalla transazione corrente. Le transazioni in esecuzione al livello READ COMMITTED generano blocchi condivisi, ma i blocchi di riga o pagina vengono rilasciati dopo la lettura della riga. In entrambi i casi, quando si esegue la scansione di un indice, se un altro utente modifica la colonna della chiave di indice della riga durante la lettura, è possibile che la riga venga visualizzata nuovamente se la modifica principale sposta la riga di una posizione in avanti nella scansione. Analogamente, la riga potrebbe non essere visualizzata se la modifica principale sposta la riga in una posizione già letta all'interno dell'indice. Per evitare questo, utilizzare l'hint SERIALIZABLE o HOLDLOCK o il controllo delle versioni delle righe. Per ulteriori informazioni, vedere Hint di tabella (Transact-SQL) e Livelli di isolamento basati sul controllo delle versioni delle righe nel Motore di database.

  • Mancare una o più righe che non rappresentano l'obiettivo dell'aggiornamento

    Quando si utilizza READ UNCOMMITTED, se la query legge righe usando una scansione di ordine di allocazione (utilizzando le pagine di IAM), è possibile perdere righe se un'altra transazione provoca la suddivisione di una pagina. Questo non può verificarsi con Read committed perché durante la suddivisione di una pagina viene usato un blocco di tabella che non si verifica se la tabella non ha un indice cluster, poiché gli aggiornamenti non provocano suddivisioni di pagine.