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

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

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

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

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

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

Ответов (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 года, но она может предоставить некоторую информацию для следующего пользователя.

Я просто хотел опубликовать здесь исправление, которое помогло нашей компании установить новое программное обеспечение. С первого дня в файле журнала клиента мы получали следующую ошибку: Сервер не может обработать запрос. ---> Ошибка транспортного уровня при получении результатов от сервера. (поставщик: поставщик TCP, ошибка: 0 - период тайм-аута семафора истек.) ---> Период тайм-аута семафора истек.

Что полностью решило проблему, так это настройка агрегатора ссылок (LAG) на нашем коммутаторе. Наш сервер Dell FX1 имеет резервные оптоволоконные линии, выходящие из задней части. Мы не понимали, что коммутатор, к которому они подключены, должен иметь LAG, настроенный на этих двух портах. Подробности см. Здесь: https://docs.meraki.com/display/MS/Switch+Ports#SwitchPorts-LinkAggregation

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

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

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

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

Вы также должны проверить подключение оборудования к базе данных.

Возможно, эта ветка будет полезна: http://channel9.msdn.com/forums/TechOff/234271-Conenction-forcible-closed-SQL-2005/

Я использую уровень надежности для своих команд БД (абстрагированных в интерфейсе репозитория). По сути, это просто код, который перехватывает любое ожидаемое исключение (DbException, а также InvalidOperationException, которое возникает при проблемах с подключением), регистрирует его, собирает статистику и повторяет все снова.

При наличии этого уровня надежности служба смогла успешно выдержать стресс-тестирование (постоянные блокировки, сбои сети и т. Д.). Производство гораздо менее враждебно, чем это.

PS: Здесь больше об этом (наряду с простым способом определения надежности с помощью DSL перехвата)

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

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

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

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

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

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

Удачи.

Это сообщение в блоге на Майкле Aspengren объясняет сообщение об ошибке «Произошла ошибка транспортного уровня при отправке запроса на сервер.»

У меня была такая же проблема, хотя и с запросами на обслуживание в базе данных SQL.

Вот что у меня было в журнале ошибок службы:


System.Data.SqlClient.SqlException: при отправке запроса на сервер произошла ошибка транспортного уровня. (поставщик: поставщик TCP, ошибка: 0 - существующее соединение было принудительно закрыто удаленным узлом.)


У меня есть набор тестов C#, который тестирует службу. Служба и БД были на внешних серверах, поэтому я подумал, что это может быть проблемой. Поэтому я развернул службу и БД локально, но безрезультатно. Вопрос продолжился. Набор тестов даже не является жестким тестом производительности, поэтому я понятия не имел, что происходит. Один и тот же тест каждый раз терпел неудачу, но когда я отключил этот тест, другой тест не удался постоянно.

Я пробовал другие методы, предложенные в Интернете, которые тоже не сработали:

  • Увеличьте значения реестра TcpMaxDataRetransmissions и TcpMaxConnectRetransmissions .
  • Отключите параметр «Общая память» в диспетчере конфигурации SQL Server в разделе «Клиентские протоколы» и отсортируйте TCP / IP до 1-го места в списке.
  • Это может произойти, когда вы тестируете масштабируемость с большим количеством попыток подключения клиентов. Чтобы решить эту проблему, используйте служебную программу regedit.exe, чтобы добавить новое значение DWORD с именем SynAttackProtect в раздел реестра HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters \ с данными значения 00000000.

Моим последним средством было использовать старость, говорящую «Попробуй и попробуй еще раз». Поэтому у меня есть вложенные операторы try-catch, чтобы гарантировать, что если соединение TCP / IP потеряно в нижнем протоколе связи, оно не просто откажется от этого, а попытается снова. Теперь это работает для меня, но это не очень элегантное решение.

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