Perché System.Transactions TransactionScope default Isolationlevel Serializable

Mi sto solo chiedendo quale sia una buona ragione per usare Serializable come il Isolationlevel predefinito quando si crea un System.Transactions TransactionScope , perché non riesco a pensare a nessuno (e sembra che non si possa cambiare il default via web/app.config modo da devi sempre impostarlo nel tuo codice)

 using(var transaction = TransactionScope()) { ... //creates a Transaction with Serializable Level } 

Invece devo sempre scrivere il codice di caldaia in questo modo:

 var txOptions = new System.Transactions.TransactionOptions(); txOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; using(var transaction = new TransactionScope(TransactionScopeOption.Required,txOptions)) { ... // } 

Qualche idea?

Il fatto che Serializable sia l’impostazione predefinita deriva dal momento in cui .NET non è stato nemmeno rilasciato (prima dell’anno 1999), dalla programmazione DTC ( Distributed Transaction Coordinator ).

DTC utilizza un enumerazione nativa ISOLATIONLEVEL :

ISOLATIONLEVEL_SERIALIZABLE I dati letti da una transazione corrente non possono essere modificati da un’altra transazione fino al termine della transazione corrente. Non è ansible inserire nuovi dati che potrebbero influire sulla transazione corrente. Questo è il livello di isolamento più sicuro ed è l’impostazione predefinita, ma consente il livello più basso di concorrenza.

.NET TransactionScope è basato su queste tecnologie.

Ora, la prossima domanda è: perché DTC definisce ISOLATIONLEVEL_SERIALIZABLE come il livello di transazione predefinito? Suppongo che sia perché DTC è stato progettato intorno all’anno 1995 (sicuramente prima del 1999). A quel tempo, lo standard SQL era SQL-92 (o SQL2).

Ed ecco cosa dice SQL-92 sui livelli di transazione:

Una transazione SQL ha un livello di isolamento che è READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ o SERIALIZABLE. Il livello di isolamento di una transazione SQL definisce il grado in cui le operazioni su dati SQL o schemi in quella transazione SQL sono influenzati dagli effetti e possono influenzare le operazioni su dati SQL o schemi in transazioni SQL concorrenti. Il livello di isolamento di una transazione SQL è SERIALIZABLE per impostazione predefinita . Il livello può essere impostato in modo esplicito dall’istruzione .

L’esecuzione di transazioni SQL simultanee a livello di isolamento SERIALIZABLE è garantita per essere serializzabile. Un’esecuzione serializzabile è definita come un’esecuzione delle operazioni di transazioni SQL in esecuzione contemporanea che produce lo stesso effetto di alcune esecuzioni seriali di quelle stesse transazioni SQL. Un’esecuzione seriale è quella in cui ogni transazione SQL viene completata fino all’inizio della successiva transazione SQL.

Un modo utile per ridurre la scrittura del codice di base è di avvolgerlo in una class di build come:

 public static class TransactionScopeBuilder { ///  /// Creates a transactionscope with ReadCommitted Isolation, the same level as sql server ///  /// A transaction scope public static TransactionScope CreateReadCommitted() { var options = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = TransactionManager.DefaultTimeout }; return new TransactionScope(TransactionScopeOption.Required, options); } } 

Quindi puoi usarlo in questo modo quando crei un ambito di transazione:

 using (var scope = TransactionScopeBuilder.CreateReadCommitted()) { //do work here } 

È ansible aggiungere altre impostazioni predefinite dell’ambito della transazione comune alla class del builder in base alle proprie esigenze.

Bene, immagino che questo sia uno di quei tipi di domande che “solo il designer saprebbe sicuramente”. Ma ecco i miei due cent in ogni caso:

Mentre Serializable è il livello di isolamento più “limitante” (relativo al blocco, in un RDBMS basato su lock, e quindi accesso simultaneo, deadlock, ecc.) È anche il livello di isolamento più “sicuro” (relativo alla coerenza dei dati).

Quindi, mentre richiede un lavoro extra in scenari come il tuo (fatto lì ;-), ha senso optare per la variante più sicura per impostazione predefinita. SQL Server (T / SQL) sceglie di utilizzare READ COMMITTED , ovviamente applicando altri motivi 🙂

Rendendolo modificabile dalla configurazione, sarebbe quindi una pessima idea, perché manipolando la configurazione si potrebbe rendere un’applicazione perfettamente funzionante a una di quelle rotte (perché potrebbe semplicemente non essere progettata per funzionare con qualcos’altro). O per cambiare argomento, “hardcoding” del livello di isolamento, puoi assicurarti che la tua applicazione funzioni come previsto. Probabilmente, il livello di isolamento non è adatto per un’opzione di configurazione (mentre il timeout della transazione è effettivamente).