IsolationLevel.ReadUncommitted блокировка чтения на другом подключении к SQL Server 2008 - PullRequest
3 голосов
/ 30 октября 2011

Привет! У меня проблема с чтением из базы данных, когда в вызывающем коде есть ожидающая транзакция.Например:

f1() {
DbTransaction t = Connection1.BeginTransaction(IsolationLevel.ReadUncommitted);
  ...
  f2();
  ...
  t.Commit();
}

f2() {
  Connection2.Execute("SELECT...");
}

Вызов функции f2 () приводит к исключению тайм-аута.

Такое поведение меня удивило, потому что я думал, что IsolationLevel даст доступ для чтения к базе,Когда я удаляю транзакцию из f1(), проблема исчезает.

Я благодарен за любые комментарии по этому вопросу и за то, как решить проблему.Я хотел бы сохранить транзакцию!

(Visual Studio 2010, C #, .NET 4.0, SQL Server 2008, уровень совместимости 80)

Ответы [ 3 ]

4 голосов
/ 30 октября 2011

Как говорит @Vijay, вам не нужно создавать здесь второе соединение, поэтому эту проблему легко решить, используя то же соединение.

Для справки, однако, чтобы объяснить, почемувторое соединение блокируется:

Ваше первое соединение работает с уровнем изоляции READ UNCOMMITTED, что может создавать эксклюзивные блокировки.В какой-то момент между созданием Connection1 и вызовом f2() вы делаете что-то для создания монопольной блокировки, которая блокирует оператор, выполняемый f2(), который выполняется с уровнем изоляции по умолчанию READ COMMITTED.

Если вы хотите увидеть, что происходит с блокировками, откройте два окна SSMS.В первом окне выполните следующие операторы:

set transaction isolation level read uncommitted
go

begin transaction 
-- alter some data
delete MyTable
waitfor delay '00:00:15'

rollback transaction

Во втором окне введите sp_lock, чтобы увидеть блокировки на MyTable.

2 голосов
/ 30 октября 2011

Я не уверен, почему вы открываете другой экземпляр подключения в f2 (), поскольку похоже, что оба подключения к одной и той же БД и серверу БД. Вы можете просто передать экземпляр Connection1 из f1 () в вызов метода f2 () и использовать его повторно.

f1()
{
    ...

    f2(Connection1);

    ...
}

f2()
{
    Connection1.Execute(SELECT...);
}
0 голосов
/ 30 октября 2011

Я предлагаю вам использовать TransactionScope в операторе using для инициирования этих транзакций. Кроме этого, повторно используйте соединение в соответствии с рекомендациями Vijay.

Я полагаю, что проблема, с которой вы столкнулись, связана со вторым соединением с той же базой данных, которое наследует транзакцию окружения от первого соединения. Я не уверен, что поставщики баз данных будут поддерживать несколько соединений с одним и тем же сервером баз данных в одном соединении.

Вы всегда можете открыть SQL studio и проверить список активных блокировок, пока второй SELECT блокирует. Довольно простой способ узнать, что именно блокирует.

...