Подтвердить что ты не робот

Как вы относитесь к ошибкам транспортного уровня в SqlConnection?

Время от времени в приложении с большим объемом .NET вы можете увидеть это исключение при попытке выполнить запрос:

System.Data.SqlClient.SqlException: ошибка транспортного уровня произошел при отправке запроса на сервер.

Согласно моим исследованиям, это то, что "просто происходит", и не так много можно сделать, чтобы предотвратить его. Это не происходит из-за плохого запроса и, как правило, не может быть дублировано. Он просто размножается, возможно, раз в несколько дней в загруженной системе OLTP, когда по какой-либо причине TCP-соединение с базой данных ухудшается.

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

У кого-нибудь есть альтернативные решения?

4b9b3361

Ответ 1

Я отправил ответ на другой вопрос по другой теме, которая может быть использована здесь. Этот ответ включал соединения SMB, а не SQL. Однако он был идентичен, поскольку он касался транспортной ошибки низкого уровня.

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

Посмотрите параметры реестра для настройки TCP/IP в Windows. В частности, вы хотите посмотреть TcpMaxDataRetransmissions и, возможно, TcpMaxConnectRetransmissions. По умолчанию они равны 5 и 2, попробуйте немного увеличить их в клиентской системе и дублируйте ситуацию загрузки.

Не сойди с ума! TCP удваивает тайм-аут при каждой последующей повторной передаче, поэтому поведение таймаута для плохих соединений может оказаться экспоненциальным, если вы увеличите их слишком много. Когда я вспоминаю, что TcpMaxDataRetransmissions до 6 или 7 решал нашу проблему в подавляющем большинстве случаев.

Ответ 3

Чтобы ответить на ваш оригинальный вопрос:

Более элегантный способ обнаружить эту конкретную ошибку без разбора сообщения об ошибке - проверить свойство Number SqlException.

(Это фактически возвращает номер ошибки из первого SqlError в коллекции Errors, но в вашем случае транспортная ошибка должна быть единственной в коллекции.)

Ответ 4

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

Моей первой точкой было бы посмотреть на сеть и убедиться, что серверы не подключены к DHCP и не обновляют IP-адреса, вызывающие эту ошибку. Если это не так, вам нужно начать трафик через журналы событий, которые ищут другие связанные с сетью.

К сожалению, как указано выше, сетевая ошибка. Главное, что вы можете сделать, это просто следить за соединениями с помощью инструмента, такого как netmon, и работать оттуда.

Удачи.

Ответ 5

использовать Enterprise Services с компонентами транзакции

Ответ 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