Domanda

Faccio parte di un team che costruisce un sito web basato su ADO.NET. A volte abbiamo diversi sviluppatori e uno strumento di test automatizzato che lavorano contemporaneamente una copia di sviluppo del database.

Usiamo il livello di isolamento dell'istantanea, che, per quanto ne so, utilizza una concorrenza ottimistica: piuttosto che bloccare, spera per il meglio e genera un'eccezione se si tenta di eseguire il commit di una transazione se le righe interessate sono state modificate da un'altra parte durante la transazione.

Per usare il livello di isolamento dell'istantanea usiamo:

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;

e in C #:

Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);

Notare che IsolationLevel Snapshot non è lo stesso di ReadCommitted Snapshot, che abbiamo anche provato, ma al momento non stiamo usando.

Quando uno degli sviluppatori entra in modalità debug e mette in pausa l'app .NET, manterrà una connessione con una transazione attiva durante il debug. Ora, mi aspetto che questo non sia un problema: dopo tutto, tutte le transazioni utilizzano il livello di isolamento dello snapshot, quindi mentre una transazione è in pausa, altre transazioni dovrebbero poter procedere normalmente poiché la transazione in pausa non contiene alcun blocco. Naturalmente, una volta completata la transazione sospesa, è probabile che rilevi un conflitto; ma è accettabile fintanto che altri sviluppatori e i test automatizzati possono procedere senza ostacoli.

Tuttavia, in pratica, quando una persona interrompe una transazione durante il debug, tutti gli altri utenti DB che tentano di accedere alle stesse righe vengono bloccati nonostante l'utilizzo del livello di isolamento dello snapshot.

Qualcuno sa perché questo accada e / o come posso ottenere una vera concorrenza ottimistica (non bloccante)? ??

La risoluzione (una sfortunata per me) : Remus Rusanu ha osservato che gli scrittori bloccano sempre altri scrittori; questo è supportato da MSDN - non è del tutto chiaro e lo dice, ma menziona sempre e solo evitando i blocchi dei lettori e degli scrittori. In breve, il comportamento che desidero non è implementato in SQL Server.

È stato utile?

Soluzione

Il livello di isolamento SNAPSHOT influenza, come tutti i livelli di isolamento, solo le letture. Le scritture si stanno ancora bloccando a vicenda. Se ritieni che ciò che vedi siano blocchi di lettura, dovresti indagare ulteriormente e verificare i tipi di risorsa e i nomi delle risorse su cui si verifica il blocco (wait_type e wait_resource in sys.dm_exec_requests ).

Non consiglierei di apportare modifiche al codice per supportare uno scenario che coinvolge gli sviluppatori a fissare il debugger per minuti. Se ritieni che questo scenario possa ripetersi in produzione (es. Blocchi del client), allora è una storia diversa. Per ottenere ciò che desideri, devi ridurre al minimo le scritture ed eseguire tutte le scritture al termine della transazione, in un'unica chiamata che si impegna prima della restituzione. In questo modo nessun client può trattenere i blocchi X per molto tempo (non può bloccarsi mentre si tiene i blocchi X). In pratica questo è piuttosto difficile da realizzare e richiede molta disciplina da parte degli sviluppatori nel modo in cui scrivono il codice di accesso ai dati.

Altri suggerimenti

Hai guardato i blocchi quando uno sviluppatore mette in pausa la transazione? Inoltre, l'attivazione del livello di isolamento dell'istantanea non ha molto effetto. Hai impostato ALLOW_SNAPSHOT_ISOLATION su?

Ecco i passaggi:

ALTER DATABASE <databasename>
SET READ_COMMITTED_SNAPSHOT ON;
GO

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

Dopo che il database è stato abilitato per l'isolamento dello snapshot, gli sviluppatori e gli utenti devono quindi richiedere che le loro transazioni vengano eseguite in questa modalità snapshot. Questo deve essere fatto prima di avviare una transazione, tramite una direttiva sul lato client sull'oggetto transazione ADO.NET o all'interno della loro query Transact-SQL usando la seguente istruzione:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

Raj

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