Общая ошибка сети после ночи бездействия
Некоторое время в нашем флагманском приложении возникали загадочные ошибки. Сообщение об ошибке является общим
[DBNETLIB][ConnectionWrite (send()).] Общая ошибка сети. Проверьте вашу сетевую документацию.
Это надежно воспроизводится, если оставить приложение открытым на ночь и возобновить работу по утрам. Так как это серверное приложение, это нормальный сценарий.
Самое смешное, что мы перешли с SQL Server 7 на 2000 и 2008, и проблема присутствует во всех из них. Но то, что кажется важным, - это ОС, на которой мы запускаем приложение. На WinXP работает нормально, на Vista/7 не получается. Так что проблема на стороне клиента.
Результаты Google по сообщению об ошибке охватывают очень широкий спектр различных причин (так как это очень общая ошибка), и ни один из найденных сценариев не похож на наш.
Так что, может быть, кто-то здесь будет знать, в чем проблема в нашем случае?
3 ответа
Вы должны быть в состоянии воспроизвести это условие ошибки по требованию:
1. Открытие соединения с базой данных (в вашем клиентском приложении)
2. Отключите сетевой кабель
3. Снова подключите сетевой кабель (дождитесь восстановления сетевого подключения).
4. Использование ранее открытого соединения для запроса базы данных
Насколько я могу судить по опыту, код ADO на стороне клиента не может последовательно определить, является ли базовое сетевое соединение действительным или нет. Проверка, открыто ли соединение с базой данных (в коде клиента), возвращает true. Однако выполнение любых операций с этим соединением приводит к General network error
,
Похоже, пул соединений может определить, когда соединение становится "плохим", поэтому он никогда не возвращает плохое соединение с приложением. Вместо этого он просто открывает новое соединение.
Таким образом, если приложение поддерживает связь с базой данных в течение длительного времени (используется или не используется) приложением, основное подключение TCP/IP может быть нарушено.
Суть в том, что соединения с базой данных должны быть закрыты и возвращены обратно в пул соединений, когда они не используются.
редактировать
Кроме того, в зависимости от количества клиентов, подключающихся к базе данных, неиспользование пула соединений может вызвать другую проблему. Вы можете использовать максимальное количество открытых сокетов на стороне сервера. Это из памяти. Как только соединение закрывается на стороне клиента, соединение на сервере переходит в состояние TIME_WAIT. По умолчанию сокет сервера закрывается примерно за 4 минуты, поэтому он не будет доступен другим клиентам в течение этого времени. Суть в том, что на сервере имеется ограниченное количество доступных сокетов. Сохранение слишком большого количества открытых соединений может создать проблему.
Один проект, над которым я работал, легко достиг предела сокетов примерно с 120 пользователями. Была добавлена новая "функция", которая полностью ударила по серверу, и после нескольких часов использования приложения все вдруг замедлилось бы для всех. SQL-сервер не закрывал достаточно сокетов во времени для новых запросов на подключение. Несмотря на то, что сокетов всего 65 КБ, ADO доступны только первые 5000 (это параметр реестра по умолчанию, поэтому его можно изменить).
Количество сокетов в состоянии TIME_WAIT будет медленно накапливаться до тех пор, пока ОС не выделит больше. Таким образом, клиенты должны были ждать, пока сокеты на стороне сервера не закроются, и тогда может быть создано новое соединение.
Была похожая ошибка. Для меня это было косвенно вызвано несовпадающими вызовами WSACleanup
а также WSAStartup
,
Программа называется WSACleanup
больше раз, чем WSAStartup
, Это приведет к тому, что счетчик ссылок (где-то в библиотеке сокетов) слишком рано достигнет нуля.
Я думаю, что с этого момента все сокеты, принадлежащие процессу, сломаны.
И это также убило бы клиент SQL, поскольку он также использует сокеты для "общения" с сервером SQL.