Почему это система.Транзакции TransactionScope по умолчанию Isolationlevel сериализуемый
мне просто интересно, что хорошего причина использовать сериализуемые как уровень изоляции по умолчанию может быть при создании System.Transactions
TransactionScope, потому что я не могу придумать ни одного (и кажется, что вы не можете изменить значение по умолчанию через web/app.config
Так что вы всегда должны установить его в своем коде)
using(var transaction = TransactionScope())
{
... //creates a Transaction with Serializable Level
}
вместо этого я всегда должен писать шаблонный код такой:
var txOptions = new System.Transactions.TransactionOptions();
txOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
using(var transaction = new TransactionScope(TransactionScopeOption.Required,txOptions))
{
... //
}
какие идеи?
3 ответа:
факт
Serializable
Это значение по умолчанию приходит со времен, когда .NET даже не был выпущен (до 1999 года), от DTC (Координатор Распределенных Транзакций) программирования.DTC использует родной устанавливается перечисление:
ISOLATIONLEVEL_SERIALIZABLE Данные, считываемые текущей транзакцией, не могут быть измененным другой транзакцией до текущей транзакции заканчивает. Новые данные не могут быть вставлены, что повлияет на текущий торговая операция. это самый безопасный уровень изоляции по умолчанию, но позволяет самый низкий уровень параллелизма.
.NET
TransactionScope
построен на основе этих технологий.теперь следующий вопрос: почему DTC определяет
ISOLATIONLEVEL_SERIALIZABLE
как уровень транзакции по умолчанию? Я полагаю, это потому, что DTC был разработан примерно в 1995 году (до 1999 года наверняка). В то время стандартом SQL был SQL-92 (или SQL2).и вот что SQL-92 говорит об уровне транзакции:
SQL-транзакция имеет уровень изоляции, который считывается незафиксированным, Read COMMITTED, REPEATABLE READ или SERIALIZABLE. Уровень изоляции SQL-транзакции определяет степень, в которой операции выполняются SQL-данные или схемы в этой SQL-транзакции зависят от влияние и может влиять на операции над SQL-данными или схемами в параллельные SQL-транзакции. изоляция уровень SQL-транзакции сериализуется по умолчанию. Уровень может быть явно установлен
<set transaction statement>
.выполнение параллельных SQL-транзакций на уровне изоляции Сериализуемый гарантированно будет сериализуемым. Сериализуемый exe- преследования определяется как выполнение операции согласны- rently выполнение SQL-транзакций, которые производят тот же эффект, что и некоторое последовательное выполнение тех же SQL-транзакций. Последовательный exe- преследования-один в который каждая SQL-транзакция выполняет до завершения перед началом следующей SQL-транзакции.
полезный способ сократить написание шаблонного кода-это обернуть его в класс builder следующим образом:
public static class TransactionScopeBuilder { /// <summary> /// Creates a transactionscope with ReadCommitted Isolation, the same level as sql server /// </summary> /// <returns>A transaction scope</returns> public static TransactionScope CreateReadCommitted() { var options = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = TransactionManager.DefaultTimeout }; return new TransactionScope(TransactionScopeOption.Required, options); } }
тогда вы можете использовать его так при создании области транзакции:
using (var scope = TransactionScopeBuilder.CreateReadCommitted()) { //do work here }
вы можете добавить другие общие области транзакций по умолчанию для класса builder, как вам это нужно.
Ну, я думаю, что это один из тех "только дизайнер определенно знает" тип вопросов. Но вот мои два цента так или иначе:
в то время как сериализуемый является наиболее "ограничивающим" уровнем изоляции (относительно блокировки, в RDBMS на основе блокировки и, следовательно, параллельного доступа, взаимоблокировок и т. д.) это также самый "безопасный" уровень изоляции (относительно согласованности данных).
поэтому, требуя дополнительной работы в сценариях, подобных вашему (было сделано это; -), имеет смысл выбираю самый безопасный вариант по умолчанию. SQL Server (T/SQL) выбирает использовать ЧИТАТЬ COMMITTED, очевидно, применяя другие причины :-)
сделать его изменяемым по конфигурации, было бы плохой идеей, потому что, играя с конфигурацией, вы могли бы сделать идеально работающее приложение сломанным (потому что оно может просто не быть разработано для работы с чем-либо еще). Или чтобы перевернуть аргумент, "жестко закодировав" уровень изоляции, вы можете убедиться, что ваш приложение работает так, как ожидалось. Возможно, уровень изоляции не подходит для параметра конфигурации (в то время как тайм-аута транзакции действительно).