Sono parte di un team che crea un sito Web basato su ADO.NET. A volte abbiamo diversi sviluppatori e uno strumento di test automatico che lavora simultaneamente a una copia di sviluppo del database.Utilizzo di IsolationLevel.Snapshot ma DB sta ancora bloccando
Utilizziamo il livello di isolamento dello snapshot, che, per quanto ne so, utilizza la concorrenza ottimistica: anziché bloccarsi, spera 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 utilizzare il livello di isolamento dello snapshot che utilizziamo:
ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;
e in C#:
Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);
noti che IsolationLevel di foto non è la stessa di READCOMMITTED Snapshot, che abbiamo anche provato, ma non sono attualmente in uso.
Quando uno degli sviluppatori entra in modalità di debug e sospende l'app .NET, terranno 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 viene messa in pausa, altre transazioni dovrebbero essere in grado di procedere normalmente poiché la transazione sospesa non contiene alcun blocco. Ovviamente, quando la transazione in pausa viene completata, è probabile che rilevi un conflitto; ma ciò è accettabile a condizione che altri sviluppatori e i test automatici possano procedere senza ostacoli.
Tuttavia, in pratica, quando una persona interrompe una transazione durante il debug, tutti gli altri utenti di DB che tentano di accedere alle stesse righe vengono bloccati nonostante l'utilizzo del livello di isolamento dello snapshot.
Qualcuno sa perché questo si verifica e/o come posso ottenere una concorrenza ottimistica (non bloccante)?
La risoluzione (uno sfortunato per me): Remus Rusanu ha notato che gli scrittori bloccano sempre altri scrittori; questo è supportato da MSDN - non viene fuori e lo dice, ma menziona solo sempre evitando i blocchi di lettore-scrittore. In breve, il comportamento che desidero non è implementato in SQL Server.
Questo comportamento è improbabile in produzione. D'altra parte, la versione di sviluppo è abbastanza importante, e sarei abbastanza disposta a apportare modifiche al codice se questo smorzerà lo sviluppo. Sfortunatamente, uno stile "svn-esque" di blocco (speranza per il meglio e semplicemente fallimento in conflitto) non sembra essere implementato. La possibilità di avere transazioni di lunga durata e complesse senza bloccare tutte le piccole transazioni sarebbe comunque utile - così come, usiamo meno transazioni che sono ideali solo per evitare il blocco. –
Non c'è un proiettile d'argento. Ma se ti trovi spesso bloccato in scrittura e scrittura dovresti considerare il motivo per cui ciò si verifica, perché le diverse 'richieste' causano aggiornamenti degli stessi dati. Forse è possibile partizionare meglio l'applicazione, ridurre la probabilità di sovrapposizione. Forse alcuni aggiornamenti possono essere posticipati, inseriti in una tabella di lavoro durante la transazione dell'utente (enque/dequeue può essere reso libero da blocchi, con cura) e successivamente elaborati da processi batch dedicati. Assicurati inoltre che tutte le transazioni blocchino solo il minimo necessario (nessun blocco di pagina/tabella, nessuna escalation, nessuna scansione di tabelle inutili). –