TransactionScope и пул соединений
Я пытаюсь понять, есть ли у нас проблема в нашем приложении с подключениями к базе данных, используя неправильные IsolationLevels. Наше приложение представляет собой приложение базы данных .Net 3.5 с использованием SQL Server 2005.
Я обнаружил, что IsolationLevel соединений не reset, когда они возвращаются в пул соединений (см. здесь) и был также очень удивлен, прочитав в этом блоге, что каждый новый созданный TransactionScope получает свой собственный пул соединений, назначенный ему.
Наши обновления баз (через наши бизнес-объекты) происходят в TransactionScope (новый для каждого обновления объекта бизнес-объекта создается). Но наши выборки не используют явную транзакцию. Так что мне интересно, можем ли мы когда-нибудь попасть в ситуацию, когда наши операции с выборкой (которые должны использовать значение IsolationLevel - Read Committed по умолчанию) будут повторно использовать соединение из пула, которое было использовано для обновления, и наследовать обновление IsolationLevel (RepeatableRead)? Или наши обновления будут гарантированно использовать другой пул соединений, поскольку они завернуты в TransactionScope?
Спасибо заранее,
Грэхэм
Ответы
Ответ 1
Это волнует!
Статья Билла Вогана, связанная с положениями о том, что "каждый TransactionScope получает свой собственный пул", но код в статье поддержки, с которой вы связались, предполагает, что это неверно, поскольку второй запуск NoTxScope()
получает соединение из пула, использующее повышенный уровень изоляции.
Вы можете "принудительно" решить проблему [я рисую код из первой ссылки]:
static void ForceReadCommitedScope()
{
TransactionOptions op = new TransactionOptions();
op.IsolationLevel = IsolationLevel.ReadCommitted;
using (TransactionScope tx = new TransactionScope(TransactionScopeOption.RequiresNew, op))
{
SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=master;Integrated Security=True;");
SqlCommand com = new SqlCommand("select transaction_isolation_level from sys.dm_exec_sessions where (session_id = @@SPID)", con);
con.Open();
short level = (short)com.ExecuteScalar();
Console.WriteLine("transaction_isolation_level : " + level.ToString());
con.Close();
tx.Complete();
}
}
или добавив "..;Pooling=False"
к вашей строке подключения.
Ответ 2
В SQL Server 2014 уровень изоляции для объединенного соединения - reset, когда соединение возвращается в пул. В более ранних версиях это не так.
Посмотреть это сообщение в форуме:
"в SQL 2014, для клиентских драйверов с TDS версии 7.3 или выше SQL-сервер будет reset уровень изоляции транзакции по умолчанию (прочитано зафиксировано) для объединенные соединения. для клиентов с версией TDS ниже 7.3 они будут иметь старое поведение при работе с SQL 2014."
Update
Это снова изменилось на предыдущее поведение в SQL 2014 CU6 и SQL 2014 SP1 CU1 с этим исправлением:
FIX: Уровень изоляции транзакции reset некорректно, когда соединение SQL Server выпущено в SQL Server 2014
"Предположим, что вы используете класс TransactionScope в исходном коде на стороне клиента SQL Server, и вы явно не открываете соединение SQL Server в транзакции. Когда соединение SQL Server освобождается, уровень изоляции транзакции составляет reset неправильно".