Сайт большого объема с использованием ADO.NET TransactionScope и ExecuteCommand на NOLOCK, ЧИТАТЬ НЕОБЕСПЕЧЕННЫЙ напрямую?
Просто прочитайте эту интересную статью Омара в своем блоге Linq to SQL, чтобы решить проблему взаимоблокировки транзакций и времени ожидания запроса с помощью незафиксированных чтений, и в конце Джавед Хасан начал спорить с ним о своем решении ситуации с nolock на сайте с большим объемом.
Здесь проблема, которую мы пытаемся решить, состоит в том, что с точки зрения SQL мы должны использовать операторы Select с NOLOCK или использовать SET TRANSACTION LEVEL READ UNCOMMITTED, в противном случае строки большого объема в БД будут заблокированы и вызовут ошибки. Используемая Омаром технология - это Linq2Sql, поэтому вопрос в том, как нам добиться этого в вашем коде доступа к данным на C#, чтобы вышеуказанное не происходило?
В основном в этом посте Омар приходит к своему решению, работая и тестируя на реальных сайтах и с такими инструментами, как SqlProfiler, в то время как Джавед Хасан приходит к своему решению с документами MSDN, блогом Скотта Хансельмана и т. Д.
Омар предлагает использовать следующее
using (var db = new DropthingsDataContext2())
{
db.Connection.Open();
db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
var user = db.aspnet_Users.First();
var pages = user.Pages.ToList();
}
тогда как Джавед Хасан предлагает
using (new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted }))
{
//Your db Operation
}
Мне очень интересно узнать, что вы, ребята, делаете по этому конкретному вопросу на большом сайте, таком как StatckOverflow, или что Джефф и их ребята сделали в этом отношении?
Изменить: После прочтения первого поста, я хочу отметить несколько вещей в посте Омара.
- он столкнулся с проблемой соединения с его подходом, но он решил ее, см. его пост.
- что еще более важно он упомянул, что попробовал использовать способ транзакции ADO.NET и даже попробовал то, что Скотт Хансельман написал в своем блоге, но это не работает для сайта с большими объемами, это несколько снижает производительность. Омар сказал, что "System.Transaction имеет значительные накладные расходы. Я никогда не мог использовать его на веб-сайте большого объема, не заставляя ЦП работать на 100%, а Req/sec снижаться до 1/10. Это сделано для корпоративных приложений, а не для высоких объем сайтов ".
4 ответа
Прежде всего, пожалуйста, избегайте незафиксированных чтений, они могут вызвать много проблем. Гораздо лучший подход - просто установить для базы данных изоляцию моментальных снимков. Это то, что сделал Джефф.
Джефф в основном сказал: "бла-бла-бла, будь реальным, бла-бла, теоретики баз данных, бла-бла, READ UNCOMMITTED может быть полезным для реальных приложений, которые не требуют согласованности данных". Джефф не администратор баз данных, к счастью, на SO здесь много администраторов баз данных.
Проблема с подходом Омара заключается в том, что он может пропускать соединения с уровнем изоляции "read uncommitted" в ваш пул соединений, что может нанести ущерб вашему веб-сайту. Значение случайного оператора может быть выполнено при чтении незафиксированным.
Подход Javed был бы намного лучше, потому что у MS есть возможность очистить соединение.
РЕДАКТИРОВАТЬ Если у вас есть проблемы с производительностью с подходом Javed, вы можете посмотреть на прокат свой собственный менеджер транзакций.
Некоторые вещи, которые вы, вероятно, хотите сделать:
- Держать стек текущих транзакций
- Подтвердите, что вы находитесь в потоке создателя, когда транзакция совершена
- Сброс изоляции транзакции до ее предыдущего состояния при утилизации
- Откат на удаление, если транзакция не была совершена.
- Поддержка вложенных откатов.
Я являюсь разработчиком группы инструментов в группе SQL Server в Microsoft. Многие приложения не являются сверхчувствительными к согласованности транзакций, особенно если вы пишете приложение, которое создает отчеты или что-то, что иногда противоречивые данные не конец света. Конечно, если вы пишете финансовое приложение или что-то еще, что очень плохо переносит несоответствие данных, вы, вероятно, захотите изучить другие решения.
Если вы решите использовать незафиксированные операции чтения, я разместил в блоге удобное решение с использованием методов расширения в C#.
{Моя (плохая) репутация мешает мне публиковать комментарии, поэтому я поставил это как ответ}
Если вы используете IsolationLevel через System.Transactions и создаете новый контекст Linq в блоке транзакции, SQL Server в конечном итоге пытается вызвать DTC для координации транзакции. Это случилось со мной и было совершенно неожиданным.
Что касается транзакций в.Net и (как-то удивительно) побочного эффекта DTC, этот документ " Представление транзакций System.Transaction в.NET Framework 2.0", написанный Ювалом Лоуи, очень хорошо объясняет ситуацию и по-прежнему полностью действителен (.Net4). Стоит прочтения. (Я бы также оставил комментарий... если бы мог.)