Domanda

Stiamo usando un database SQL Server 2005 (senza controllo delle versioni delle righe) con un'enorme istruzione select e stiamo vedendo che blocca l'esecuzione di altre istruzioni (visto usando sp_who2 ). Non pensavo che le istruzioni SELECT potessero causare il blocco - c'è qualcosa che posso fare per mitigare questo?

È stato utile?

Soluzione

SELECT può bloccare gli aggiornamenti. Un modello di dati e una query progettati correttamente causano solo un blocco minimo e non rappresentano un problema. Il suggerimento "solito" di NOLOCK è quasi sempre la risposta sbagliata. La risposta corretta è ottimizzare la query in modo che non esegua la scansione di tabelle enormi.

Se la query non è sintonizzabile, è necessario innanzitutto considerare Livello ISOLATION SNAPSHOT , in secondo luogo dovresti considerare l'utilizzo di DATABASE SNAPSHOTS e l'ultima opzione dovrebbe essere DIRTY LEGGI (ed è meglio cambiare il livello di isolamento piuttosto che usare NOLOCK SUGGERIMENTO). Si noti che le letture sporche, come indica chiaramente il nome, restituiranno dati incoerenti (ad esempio, il foglio totale potrebbe essere sbilanciato).

Altri suggerimenti

Da documentazione :

  I blocchi

?? Shared (S) consentono alle transazioni simultanee di leggere (SELECT) una risorsa sotto il controllo pessimistico della concorrenza. Per ulteriori informazioni, vedere Tipi di controllo della concorrenza . Nessun'altra transazione può modificare i dati mentre esistono blocchi condivisi (S) sulla risorsa. I blocchi condivisi (S) su una risorsa vengono rilasciati al termine dell'operazione di lettura, a meno che il livello di isolamento della transazione non sia impostato su lettura ripetibile o superiore o venga utilizzato un suggerimento di blocco per conservare blocchi condivisi (S) per la durata della transazione.

Un blocco condiviso è compatibile con un altro blocco condiviso o un blocco di aggiornamento, ma non con un blocco esclusivo.

Ciò significa che le tue query SELECT bloccheranno le query UPDATE e INSERT e viceversa.

Una query SELECT inserirà un blocco condiviso temporaneo quando legge un blocco di valori dalla tabella e lo rimuoverà al termine della lettura.

Per il momento in cui esiste il blocco, non sarai in grado di fare nulla con i dati nell'area bloccata.

Due query SELECT non si bloccheranno mai (a meno che non siano SELEZIONA PER AGGIORNAMENTO )

È possibile abilitare il livello di isolamento SNAPSHOT sul database e utilizzarlo, ma si noti che non impedirà il blocco delle query UPDATE da SELECT query (che sembra essere il tuo caso).

Tuttavia, impedirà che le query SELECT vengano bloccate da UPDATE .

Si noti inoltre che SQL Server , a differenza di Oracle , utilizza il gestore dei blocchi e mantiene i blocchi in un elenco collegato in memoria.

Ciò significa che sotto carico pesante, il semplice fatto di posizionare e rimuovere un blocco potrebbe essere lento, poiché l'elenco collegato dovrebbe essere bloccato dal thread di transazione.

Per eseguire letture sporche puoi:

 using (new TransactionScope(TransactionScopeOption.Required, 
 new TransactionOptions { 
 IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
 {
 //Your code here
 }

o

SelectCommand = "SELECT * FROM Table1 WITH (NOLOCK) INNER JOIN Table2 WITH (NOLOCK) ..."

ricorda che devi scrivere WITH (NOLOCK) dopo ogni tabella che vuoi leggere sporco

È possibile impostare il livello di transazione leggere Non confermato

Potresti anche ottenere deadlock:

"deadlock che coinvolgono solo una tabella" http: // sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx

e o risultati errati:

" Seleziona in READ COMMITTED e REPEATABLE READ potrebbe restituire risultati errati. "

http://www2.sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/10/selects-under-read-committed-and-repeatable-read-may-return -incorrect-results.aspx

Puoi usare il suggerimento per la tabella WITH (READPAST) . È diverso da WITH (NOLOCK) . Riceverà i dati prima dell'avvio della transazione e non bloccherà nessuno. Immagina di aver eseguito la dichiarazione prima dell'inizio della transazione.

SELECT * FROM table1  WITH (READPAST)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top