NOLOCK LINQ-to-SQL (НЕ ЧИТАЕТ, НЕ ПРИНЯТО) - PullRequest
4 голосов
/ 13 декабря 2011

Я уже некоторое время ищу здесь и в других местах и ​​не могу найти хорошего ответа на вопрос, почему нельзя использовать Linq-TO-SQL с NOLOCK ..

Каждый раз, когда я ищукак применить подсказку with (NOLOCK) к контексту Linq-To-SQL (примененному к оператору 1 sql), люди часто отвечают за принудительное выполнение транзакции (TransactionScope) с IsolationLevel, для которого установлено значение ReadUncommitted.Что ж, они редко говорят, что это приводит к тому, что соединение открывает транзакцию (которую я тоже где-то читал, нужно обязательно закрыть вручную).

Использование ReadUncommitted в моем приложении как есть, на самом деле не так уж хорошо. Сейчас я использую контекстные операторы для одного и того же соединения друг с другом.Например:

using( var ctx1 = new Context()) {
    ... some code here ...
    using( var ctx2 = new Context()) {
        ... some code here ...
        using( var ctx3 = new Context()) {
            ... some code here ...
        }
        ... some code here ...
    }
    ... some code here ...
}

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

Таким образом, одной из многих причин для перехода на nolock является предотвращение взаимных блокировок (сейчас у нас 1 тупик клиента в день).Следствием вышесказанного является просто еще один вид тупика, который на самом деле не решает мою проблему.

Итак, я знаю, что могу сделать следующее:

  1. Избегать вложенного использования одного и того же соединения
  2. Увеличение размера пула соединений на сервере

Но моя проблема заключается в следующем:

  1. Это невозможно в ближайшем будущем из-за большого количества строк кода.и это будет конфликтовать с архитектурой (даже не начав комментировать, хорошо это или плохо)
  2. Даже если это, конечно, сработает, это то, что я бы назвал «симптоматическим лечением» - как я это понимаюне знаю, насколько сильно вырастет приложение, и будет ли это надежным решением на будущее (и тогда я могу столкнуться с еще худшей ситуацией с гораздо большим количеством пользователей)

Мои мыслиявляются:

  1. Действительно ли верно, что NoLock невозможен (для каждого оператора без запуска транзакций)?
  2. Если 1 - правда, может ли это быть на самом деле нет?кто-то другой получил эту проблему и решил ее в общей модификации linq to sql?
  3. Если 2 верно - почему это не проблема для других?
    1. Есть ли другой обходной путь, на который я, возможно, не обращал внимания?
    2. Много раз использование одного и того же соединения (вложенного) является настолько плохой практикой, что ни у кого нет этой проблемы?

1 Ответ

2 голосов
/ 13 декабря 2011

1: LINQ-to-SQL действительно не позволяет указывать такие подсказки, как NOLOCK; позволяет написать собственный TSQL и использовать ExecuteQuery<T> и т. д.

2: изящное решение было бы довольно сложно, честно говоря;и есть большая вероятность, что вы будете использовать его не по назначению.Например, в сценарии «тупиковой ситуации» я бы поспорил, что на самом деле это UPDLOCK, который вы должны использовать (во время первого чтения), чтобы гарантировать, что первое чтение займет блокировку write ;это предотвращает повторный запрос на получение блокировки read , поэтому вместо взаимоблокировки вы обычно получаете блокировку

3: использование соединения не обязательно является большой проблемой (хотя обратите внимание, что new Context() не будет обычно совместно использовать соединение; чтобы поделиться соединением, вы бы использовали new Context(connection)).Если вы видите эту проблему, есть три вероятных решения (если исключить «использовать ORM с поддержкой подсказок»):

  • с использованием явной транзакции (которая не имеет длябыть TransactionScope - это может быть транзакция уровня соединения) для указания уровня изоляции
  • написать свой собственный TSQL с подсказками
  • использовать уровень изоляции уровня соединения (отмечая предостережение, которое я добавил каккомментарий)

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

...