Как вы относитесь к ошибкам транспортного уровня в SqlConnection?
Время от времени в приложении с большим объемом .NET вы можете увидеть это исключение при попытке выполнить запрос:
System.Data.SqlClient.SqlException: ошибка транспортного уровня произошел при отправке запроса на сервер.
Согласно моим исследованиям, это то, что "просто происходит", и не так много можно сделать, чтобы предотвратить его. Это не происходит из-за плохого запроса и, как правило, не может быть дублировано. Он просто размножается, возможно, раз в несколько дней в загруженной системе OLTP, когда по какой-либо причине TCP-соединение с базой данных ухудшается.
Я вынужден обнаруживать эту ошибку, анализируя сообщение об исключении, а затем повторяю всю операцию с нуля, чтобы включить использование нового соединения. Ничего из этого довольно.
У кого-нибудь есть альтернативные решения?
Ответы
Ответ 1
Я отправил ответ на другой вопрос по другой теме, которая может быть использована здесь. Этот ответ включал соединения SMB, а не SQL. Однако он был идентичен, поскольку он касался транспортной ошибки низкого уровня.
Мы обнаружили, что в ситуации с тяжелой нагрузкой удаленному серверу довольно легко отключать соединения на уровне TCP просто потому, что сервер занят. Одной из причин было то, что по умолчанию количество попыток повторной передачи данных в Windows не подходит для нашей ситуации.
Посмотрите параметры реестра для настройки TCP/IP в Windows. В частности, вы хотите посмотреть TcpMaxDataRetransmissions и, возможно, TcpMaxConnectRetransmissions. По умолчанию они равны 5 и 2, попробуйте немного увеличить их в клиентской системе и дублируйте ситуацию загрузки.
Не сойди с ума! TCP удваивает тайм-аут при каждой последующей повторной передаче, поэтому поведение таймаута для плохих соединений может оказаться экспоненциальным, если вы увеличите их слишком много. Когда я вспоминаю, что TcpMaxDataRetransmissions до 6 или 7 решал нашу проблему в подавляющем большинстве случаев.
Ответ 2
Этот сообщение в блоге Майкл Аспенгрен объясняет сообщение об ошибке "Ошибка транспортного уровня произошла при отправке запроса на сервер".
Ответ 3
Чтобы ответить на ваш оригинальный вопрос:
Более элегантный способ обнаружить эту конкретную ошибку без разбора сообщения об ошибке - проверить свойство Number
SqlException
.
(Это фактически возвращает номер ошибки из первого SqlError
в коллекции Errors
, но в вашем случае транспортная ошибка должна быть единственной в коллекции.)
Ответ 4
Я видел это в моей собственной среде несколько раз. Клиентское приложение в этом случае устанавливается на многих машинах. Некоторые из этих машин, как оказалось, являются ноутбуками, которые люди оставляют приложение открытым, отключая его, а затем снова подключая его и пытаясь использовать. Это приведет к ошибке, о которой вы упомянули.
Моей первой точкой было бы посмотреть на сеть и убедиться, что серверы не подключены к DHCP и не обновляют IP-адреса, вызывающие эту ошибку. Если это не так, вам нужно начать трафик через журналы событий, которые ищут другие связанные с сетью.
К сожалению, как указано выше, сетевая ошибка. Главное, что вы можете сделать, это просто следить за соединениями с помощью инструмента, такого как netmon, и работать оттуда.
Удачи.
Ответ 5
использовать Enterprise Services с компонентами транзакции
Ответ 6
Вы также должны проверить подключение оборудования к базе данных.
Возможно, этот поток будет полезен:
http://channel9.msdn.com/forums/TechOff/234271-Conenction-forcibly-closed-SQL-2005/
Ответ 7
Я использую уровень надежности вокруг своих команд БД (абстрагировался в interforme репозитория). В основном это просто код, который перехватывает любое ожидаемое исключение (исключение DbException, а также InvalidOperationException, которое, как правило, возникает из-за проблем с подключением), регистрирует его, фиксирует статистику и снова пытается повторить все.
С учетом этого уровня надежности службе удалось изящно выдержать стресс-тестирование (постоянные блокировки, сетевые сбои и т.д.). Производство гораздо менее враждебно, чем это.
PS: Здесь больше об этом (наряду с простым способом определения надежности с помощью DSL перехвата)
Ответ 8
У меня была та же проблема. Я спросил своих друзей-друзей, и все сказали, что люди ответили здесь: это связь между компьютером и сервером базы данных. В моем случае это был мой интернет-провайдер, или там был маршрутизатор. После обновления маршрутизатора проблема исчезла. Но есть ли у вас какие-либо другие отказы от подключения к Интернету с вашего компьютера или сервера? У меня был...
Ответ 9
У меня была такая же проблема, хотя это было с запросами на обслуживание SQL DB.
Это то, что у меня было в журнале ошибок службы:
System.Data.SqlClient.SqlException: при отправке запроса на сервер произошла ошибка транспортного уровня. (поставщик: поставщик TCP, ошибка: 0 - существующее соединение было принудительно закрыто удаленным хостом.)
У меня есть набор тестов С#, который проверяет службу. Служба и БД были на внешних серверах, поэтому я думал, что это может быть проблемой. Поэтому я развернул службу и базу данных локально безрезультатно. Вопрос продолжился. Набор тестов не является даже серьезным испытанием на производительность, поэтому я понятия не имел, что происходит. Один и тот же тест терпел неудачу каждый раз, но когда я отключил этот тест, другой будет терпеть неудачу непрерывно.
Я пробовал другие методы, предлагаемые в Интернете, которые тоже не работали:
- Увеличьте значения реестра TcpMaxDataRetransmissions и TcpMaxConnectRetransmissions.
- Отключите параметр "Общая память" в диспетчере конфигурации SQL Server в разделе "Клиентские протоколы" и выполните сортировку TCP/IP до 1-го списка.
- Это может произойти, если вы проверяете масштабируемость с большим количеством попыток подключения к клиенту. Чтобы устранить эту проблему, используйте утилиту regedit.exe, чтобы добавить новое значение DWORD с именем SynAttackProtect в раздел реестра HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\со значениями данных 00000000.
Моим последним прибежищем было использовать старость, говорящую "Попробуй и попробуй еще раз". Поэтому у меня есть вложенные утверждения try-catch, чтобы убедиться, что если TCP/IP-соединение потеряно в нижнем протоколе связи, он просто не сдаётся, а пытается снова. Теперь это работает для меня, однако это не очень изящное решение.
Ответ 10
Насколько я могу судить, класс 20 - это уровень транспорта.
Ответ 11
Сегодня утром в SSMS я столкнулся с транспортной ошибкой при подключении к SQL 2008 R2 Express.
Я пытался импортировать CSV с \r\n. Я закодировал свой ограничитель строки для 0x0d0x0a. Когда я изменил его на 0x0a, ошибка остановилась. Я могу изменить его взад и вперед и наблюдать, как это происходит/не происходит.
BULK INSERT #t1 FROM 'C:\123\Import123.csv' WITH
( FIRSTROW = 1, FIELDTERMINATOR = ',', ROWTERMINATOR = '0x0d0x0a' )
Я подозреваю, что я не пишу свой ограничитель строк правильно, потому что SQL анализирует один символ за раз, пока я пытаюсь передать два символа.
Во всяком случае, этой ошибке сейчас 4 года, но она может предоставить немного информации для следующего пользователя.
Ответ 12
Я просто хотел опубликовать исправление, которое работало для нашей компании на новом программном обеспечении, которое мы установили. Мы получили следующую ошибку с первого дня в файле журнала клиента: серверу не удалось обработать запрос. --- > При получении результатов с сервера произошла ошибка транспортного уровня. (поставщик: поставщик TCP, ошибка: 0 - период таймаута семафора истек.) --- > Срок таймаута семафора истек.
Что было полностью исправлено, проблема заключалась в создании агрегата ссылок (LAG) на нашем коммутаторе. Наш сервер Dell FX1 имеет избыточные линии волокон, выходящие из его задней части. Мы не понимали, что переключатель, к которому они подключены, необходим для настройки LAG на этих двух портах. Подробнее здесь: https://docs.meraki.com/display/MS/Switch+Ports#SwitchPorts-LinkAggregation