2012-02-29 6 views
7

Ho implementato SqlTransaction in C# per iniziare, eseguire il commit e eseguire il rollback della transazione. Tutto sta andando bene, ma ho qualche problema durante l'accesso a quelle tabelle che sono in connessione durante la transazione. Non sono riuscito a leggere la tabella durante la transazione (quelle tabelle che sono in transazione). Durante la ricerca di questo, ho scoperto che succede a causa di un blocco esclusivo. Ogni successiva selezione su quei dati a sua volta deve attendere il rilascio del blocco esclusivo. Quindi, ho superato tutti i livelli di isolamento forniti da SqlTransaction, ma non ha funzionato. Quindi, devo rilasciare il blocco esclusivo durante la transazione in modo che l'altro utente possa avere accesso a quella tabella e possa leggere i dati. Esiste un metodo per raggiungere questo obiettivo? Grazie in anticipo.Livello di isolamento in Sql Transazione

Ecco il mio codice C# per la transazione

try 
{ 
    SqlTransaction transaction = null;       
    using (SqlConnection connection=new SqlConnection(Connection.ConnectionString)) 
    { 
     connection.Open(); 
     transaction=connection.BeginTransaction(IsolationLevel.Snapshot,"FaresheetTransaction");    
     //Here all transaction occurs 
     if (transaction.Connection != null) 
     {  
       transaction.Commit(); 
       transaction.Dispose(); 
     } 
    } 
} 
catch (Exception ex) 
{ 
    if (transaction.Connection != null) 
     transaction.Rollback(); 
    transaction.Dispose(); 
} `       

Questo codice sta lavorando bene, ma il problema è che quando accedo i dati di tabelle (quelli accessibili durante la transazione) durante il periodo di transazione. Le tabelle sono accessibili da altre parti dell'applicazione. Quindi, quando ho provato a leggere i dati dal tavolo, genera un'eccezione.

+1

Qual è la vostra intenzione qui? No, non prendere il blocco durante l'aggiornamento? o per altri lettori ignorare le serrature? (che ci sono per ottime ragioni) –

+1

Non voglio avere il blocco nella tabella transata per altri utenti .... la transazione può durare a lungo perché al momento della transazione, dieci di migliaia di inserimenti di dati nella tabella, quindi probabilmente ci vorrà molto tempo ... Quindi, al momento del tran saction, voglio che l'altro utente abbia accesso a quel tavolo e possa leggere i dati ....... –

risposta

14

Una transazione SQL è, in base alla progettazione, ACID. In particolare, è l '"io" che ti fa male qui - questo è progettato per impedire ad altre connessioni di vedere lo stato intermedio incoerente.

collegamento lettura individuo può scegliere di ignorare questa regola utilizzando la NOLOCK suggerimento, o il livello di isolamento READ UNCOMMITTED, ma suona come che vogliamo è che la scrittura connessione a non prendere le serrature. Bene, non succederà.

Tuttavia, ciò che forza aiuto è per i lettori di utilizzare snapshot isolamento, che realizza l'isolamento senza che il lettore prendere serrature (cercando in, come suggerisce il nome, uno shapshot point-in-time dello stato coerente quando la transazione è iniziata).

Tuttavia, IMO sarebbe meglio consigliato di vedere i due:

  • multipla, più granulare, le transazioni dallo scrittore
  • svolgere il lavoro in una tabella di gestione temporanea (una copia parallela dei dati) , poi la fusione che nelle reali dati di in pochi/aggiornare/cancellare le operazioni di massa-insert, riducendo al minimo il tempo di transazione

il primo è più semplice.

Il fatto è semplice: se si esegue una transazione di lunga durata che funziona su molti dati, si verificheranno problemi. Questo è il motivo per cui non lo fai . Il sistema funziona correttamente.

+2

la tua seconda soluzione è praticamente ciò che l'isolamento dello snapshot sta facendo per te quando è usato per una transazione che esegue scritture;) – ntziolis

+0

Ho usato il livello di isolamento dello snapshot ma di nuovo dà lo stesso problema ....In realtà funziona quando uso "select * from tbl_name with (nolock)" ma questa selezione non è appropriata per me a causa di: 1. Visualizza già i dati della transazione che deve ancora essere eseguita. 2. la tabella è già stata interrogata dall'applicazione quindi non è possibile per me passare attraverso tutte le query nel codice e modificarlo ...... –

+1

@ akash88 è il ** reader ** che deve utilizzare l'isolamento dell'istantanea; se non fosse d'aiuto, allora mi chiedo se tu non abbia semplicemente abilitato l'isolamento dello snapshot. Ma fondamentalmente, stai cercando di fare qualcosa contro il sistema. Un esempio equivalente potrebbe essere "Ho un grande file aperto mentre riscrivo grandi blocchi di esso, non voglio consentire l'accesso condiviso perché poi i lettori vedrebbero le modifiche in corso, ma non il file è bloccato finché non chiudo come posso risolvere questo problema? " risposta: non lo fai; si progetta il sistema in modo diverso. –

3

Provare ad eseguire le letture anche all'interno di una transazione e utilizzare il livello di isolamento READ UNCOMMITTED. Questo consentirà di evitare la lettura di essere bloccato, ma potrebbe produrre risultati non validi:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED  
BEGIN TRANSACTION 

SELECT * FROM Table 

COMMIT TRANSACTION 

C'è un equivoco che si tratti di operazioni/livelli di isolamento importa solo durante la scrittura, quando in realtà è altrettanto importante durante la lettura.

+0

Grazie per la risposta ..... Ho usato tutti i tipi di livello di isolamento ma potrebbe funzionare con il mio scenario. ..In realtà, lo sto usando in C# usando il metodo BeginTransaction() di SqlTransaction .... Voglio dare accesso ad altri utenti per quelle tabelle che sono in attesa di transazione ..... Ma, in ogni livello di isolamento, esclusivo sta accadendo il blocco ........ –

+0

Se stai scrivendo al tavolo le serrature esclusive sono obbligatorie. L'unica eccezione è quando si utilizza lo snapshot del livello di isolamento, ma per quanto ne so questo è disponibile solo a partire da sql 2008. Quindi l'unico modo per consentire la lettura è quello di leggere il livello di isolamento non memorizzato o caos durante le letture come descritto sopra – ntziolis

+0

Just controllato, l'isolamento dell'istantanea è già disponibile in SQL 2005, quindi ecco fatto. Usa l'isolamento dell'istantanea quando scrivi e dovresti essere bravo. Poiché sembra che tu stia leggendo solo nelle altre operazioni, non ci dovrebbero essere problemi con questo. – ntziolis

2

Il problema non è sul livello di scrittura nel database ma sul livello dei valori di lettura. Stai provando a leggere i valori che stai inserendo. Tenta di modificare la query di selezione a seguire:

select * from your_table_with_inserts with (nolock) 

tuttavia questo ignora livello di isolamento della transazione corrente e può causare letture sporche.

Quindi la domanda è: se si utilizza la transazione su tutte le query o solo inserire/aggiornare?

1

@ AKASH88, SNAPSHOT livello di isolamento è quello che stai cercando.

Si dice che anche con SNAPSHOT non funziona come previsto, sta accadendo un blocco esclusivo, posso capire che ho avuto lo stesso problema.

Assicurarsi di non abilitare solo SNAPSHOT sulle opzioni del database, ma anche READ COMMITTED SNAPSHOT deve essere attivato.

enter image description here

Si tratta di SQL Server 2008, quindi è ancora incerto se questa risposta vi aiuterà :(

i migliori saluti!