Сайт большого объема, использующий ADO.NET TransactionScope против ExecuteCommand при NOLOCK, СЧИТЫВАЕТ НЕЗАФИКСИРОВАННЫЕ данные напрямую?
-
06-07-2019 - |
Вопрос
Просто прочтите эту интересную статью Омара в его блоге Linq to SQL решает проблему взаимоблокировки транзакций и тайм-аута запроса с помощью незафиксированных операций чтения и в конце Джавед Хасан начал спорить с ним о его решении ситуации с блокировкой на сайте большого объема.
Здесь проблема, которую пытаются решить, заключается в том, что с точки зрения 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 Способ транзакции и даже попробовал то, что Скотт Хансельман написал в своем блоге, но это не работает для сайтов большого объема, это немного снижает производительность.Омар сказал, что эта "Система.Транзакции сопряжены со значительными накладными расходами.Мне никогда не удавалось использовать его на веб-сайте большого объема без того, чтобы процессор не работал на 100%, а производительность в секунду снизилась до 1/10.Он создан для корпоративных приложений, а не для сайтов большого объема ".
Решение
Прежде всего, пожалуйста, избегайте незафиксированных операций чтения, они могут вызвать множество проблем.Гораздо лучший подход - просто установить базу данных в изоляция моментального снимка. Это то , что сделал Джефф.
Джефф в основном сказал:"бла-бла-бла, будьте настоящими, бла-бла-бла, теоретики баз данных, бла-бла-бла, ЧТЕНИЕ UNCOMMITTED может быть полезно для РЕАЛЬНЫХ производственных приложений, которым не нужна согласованность данных ". Джефф не является администратором базы данных, к счастью, здесь, на SO, есть много администраторов баз данных.
Проблема с подходом Omar заключается в том, что он может привести к утечке соединений с уровнем изоляции "read uncommitted" в ваш пул подключений, что может привести к хаосу на вашем веб-сайте.Значение случайного оператора может быть выполнено в режиме read uncommitted.
Подход Javed был бы намного лучше, потому что при dispose у MS есть возможность очистить данные в соединении.
Редактировать Если у вас возникли проблемы с производительностью при использовании подхода Javed, вы могли бы рассмотреть возможность создания собственного менеджера транзакций.
Некоторые вещи, которые вы, вероятно, хотите сделать:
- Хранить стопку текущих транзакций
- Подтвердите, что вы находитесь в потоке создателя, когда транзакция будет зафиксирована
- Сбросьте изоляцию транзакции до ее предыдущего состояния при dispose
- Откат при удалении, если транзакция не была зафиксирована.
- Поддержка вложенных откатов.
Другие советы
Я разработчик в команде инструментов группы SQL Server в Microsoft.Многие приложения не слишком чувствительны к согласованности транзакций, особенно если вы пишете приложение, которое создает отчеты или что-то еще, где иногда противоречивые данные - это еще не конец света.Конечно, если вы пишете финансовое приложение или что-то еще, имеющее очень низкую устойчивость к несогласованности данных, вы, вероятно, захотите изучить другие решения.
Если вы решите использовать незафиксированные чтения, у меня есть написал в блоге удобное решение использование методов расширения в C #.
{Моя (плохая) репутация не позволяет мне публиковать комментарии, поэтому я помещаю это в качестве ответа}
Если вы используете IsolationLevel через System.Transactions и создаете новый контекст Linq в блоке transaction, SQL Server в конечном итоге пытается вызвать DTC для координации транзакции.Это только что случилось со мной и было совершенно неожиданно.
Что касается транзакций в .Net и (почему-то неожиданного) побочного эффекта DTC, этот документ Знакомство с системой.Транзакции в .NET Framework 2.0 автор: Юваль Лоуи, все очень хорошо объясняет и по-прежнему полностью актуален (.Net4).Стоит почитать.(Я бы также разместил комментарий...если бы я мог.)