Соединения JDBC от Linux до MS SQL Server 2008 истекают через 40 секунд - PullRequest
5 голосов
/ 07 июня 2011

[ См. Обновления внизу ]

Я использую JDBC для запуска операторов против SQL Server 2008 R2 на компьютере под управлением Windows 2008 R2 с компьютера под управлением Ubuntu 10.04 LTS с 2.6.32-32-серверное ядро.Я использую текущую сборку Sun Java 6 для Ubuntu (sun-java6-jdk 6.24-1build0.10.04.1) и текущий драйвер MS JDBC 3.0 (sqljdbc_3.0.1301.101_enu).

Когда выполняется операторболее 40 секунд до завершения, и он не возвращает ResultSet (например, «stmt.executeUpdate (« SELECT * INTO BAR FROM FOO »)»), программа завершается сбросом соединения:

Exception in thread "main" com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:1352)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:1339)
    at com.microsoft.sqlserver.jdbc.TDSChannel.read(IOBuffer.java:1654)
    at com.microsoft.sqlserver.jdbc.TDSReader.readPacket(IOBuffer.java:3694)
    at com.microsoft.sqlserver.jdbc.TDSCommand.startResponse(IOBuffer.java:5022)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.doExecuteStatement(SQLServerStatement.java:773)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement$StmtExecCmd.doExecute(SQLServerStatement.java:676)
    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:4575)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1400)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:179)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:154)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeUpdate(SQLServerStatement.java:633)
    at TestTimeout.main(TestTimeout.java:42)

Если мой оператор возвращает ResultSet (например, «ResultSet res = stmt.executeQuery (« SELECT * FROM FOO »)»), время соединения не истекает.

Когда я выполняю тот же оператор, не возвращаяResultSet для копии базы данных в SQL2005 на Win2003R2, оператор завершается без сброса соединения за 40 секунд.

Я включил ведение журнала и сравнил журналы для оператора SQL2005, который заканчивается с оператором SQL2008R2, который не выполняетфиниш, и они эквивалентны строка за строкой вплоть до сообщения о сбросе соединения в запросе 2008 года;см. строку в 12:54:47 вечера:

Jun 6, 2011 12:54:07 PM com.microsoft.sqlserver.jdbc.TDSCommand onRequestComplete
FINEST: TDSCommand@7ac2b2f6 (SQLServerStatement:1 executeXXX): request complete
Jun 6, 2011 12:54:07 PM com.microsoft.sqlserver.jdbc.TDSCommand startResponse
FINEST: TDSCommand@7ac2b2f6 (SQLServerStatement:1 executeXXX): Reading response...
Jun 6, 2011 12:54:47 PM com.microsoft.sqlserver.jdbc.TDSChannel read
FINE: TDSChannel (ConnectionID:1) read failed:Connection reset
Jun 6, 2011 12:54:47 PM com.microsoft.sqlserver.jdbc.SQLServerException logException
FINE: *** SQLException:ConnectionID:1 com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset Connection reset
Jun 6, 2011 12:54:47 PM com.microsoft.sqlserver.jdbc.SQLServerException logException
FINE: com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:1352)com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:1339)com.microsoft.sqlserver.jdbc.TDSChannel.read(IOBuffer.java:1654)com.microsoft.sqlserver.jdbc.TDSReader.readPacket(IOBuffer.java:3694)com.microsoft.sqlserver.jdbc.TDSCommand.startResponse(IOBuffer.java:5022)com.microsoft.sqlserver.jdbc.SQLServerStatement.doExecuteStatement(SQLServerStatement.java:773)com.microsoft.sqlserver.jdbc.SQLServerStatement$StmtExecCmd.doExecute(SQLServerStatement.java:676)com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:4575)com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1400)com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:179)com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:154)com.microsoft.sqlserver.jdbc.SQLServerStatement.executeUpdate(SQLServerStatement.java:633)TestTimeout.main(TestTimeout.java:42)
[...]

Вот соответствующие строки из оператора для базы данных 2005 года, которая работает:

Jun 6, 2011 2:02:20 PM com.microsoft.sqlserver.jdbc.TDSCommand onRequestComplete
FINEST: TDSCommand@4737371 (SQLServerStatement:1 executeXXX): request complete
Jun 6, 2011 2:02:20 PM com.microsoft.sqlserver.jdbc.TDSCommand startResponse
FINEST: TDSCommand@4737371 (SQLServerStatement:1 executeXXX): Reading response...
Jun 6, 2011 2:02:57 PM com.microsoft.sqlserver.jdbc.TDSChannel logPacket
FINEST: /XXX.XXX.XXX.XXX:60091 SPID:73 TDSReader@6 (ConnectionID:1) received Packet:1 (13 bytes)
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX   .....I..........
XX XX XX XX XX                                    .....
Jun 6, 2011 2:02:57 PM com.microsoft.sqlserver.jdbc.TDSCommand onResponseEOM
FINEST: TDSCommand@4737371 (SQLServerStatement:1 executeXXX): disabling interrupts
Jun 6, 2011 2:02:57 PM com.microsoft.sqlserver.jdbc.TDSReader nextPacket
FINEST: TDSReader@6 (ConnectionID:1) Moving to next packet -- unlinking consumed packet
Jun 6, 2011 2:02:57 PM com.microsoft.sqlserver.jdbc.TDSParser parse
FINEST: TDSReader@6 (ConnectionID:1): getNextResult: Processing TDS_DONE (0xFD)
[...] 

Я использовал tcpdump для захвата всего трафикамежду хостом SQL Server и хостом Linux, а также всем трафиком ICMP, и я заметил, что серверы 2008 и 2005 гг. отправляют Linux пакет поддержки TCP через 30 секунд после начала выполнения оператора;узел Linux подтверждает подтверждение активности с сервера 2005 года с помощью ACK, но при подключении к серверу 2008 года узел Linux не отправляет подтверждение ACK, а сервер 2008 повторно передает подтверждение активности 9 раз (один раз в секунду) перед сбросомсоединение (отсюда 40-секундный период до истечения времени ожидания).Теперь я заметил, что существует разница между пакетами поддержки активности, передаваемыми хостами Win2003 / SQL2005 и Win2008R2 / SQL2008R2: более новая ОС использует масштабирование окна TCP с размером окна 66560. Так что теперь мне интересно, если размер окна TCP> 65535вызывает iptables или стек tcp / ip на машине Linux, чтобы игнорировать пакет в молчании.Но тогда другие пакеты ранее в соединении также имеют масштабированный размер окна 66560, и они подтверждаются сервером Linux.В файлах журналов нет ничего, что указывало бы на то, что эти пакеты отбрасываются или вызывают какие-либо проблемы.

И последнее замечание: в ходе устранения этой проблемы нам пришлось перезагрузить сервер Linux.пару раз из-за обновлений, и оба раза соединения работали без перерыва в течение одного или двух дней.

Так что я озадачен, и я надеюсь, что один из вас может иметь подсказку для меня.

Обновление

Я обнаружил, что могу устранить время ожидания подключения, отключив временные метки tcp на сервере Linux.Отключение масштабирования окна не влияет на проблему.Преследование последствий отключения временных меток tcp кажется больше вопросом для serverfault.com, поэтому я посмотрю о переносе этого вопроса туда.

Обновление 2

Сравнение трассировок пакетов для работающего соединения (Win2003 / SQL2003) с тем, которое не работает (Win2008R2 / SQL2008R2), я заметил, чтоу keepalive для соединения Win2003 нет опций (даже если он использует временные метки tcp в более ранних пакетах), а для keepalive для разорванного соединения (если не отключены временные метки) в keepalive есть опции tcp, а именно временные метки.Так что теперь похоже, что машина Ubuntu отвечает на keepalive без параметров tcp, но игнорирует keeplives с параметрами tcp.Это действительно вопрос о проблемах tcp / ip на двух хостах.

Окончательное обновление Я занимался этим вопросом в списке сетевых разработчиков Linux, и теперь я убежден, что проблема связана с ошибкой Windows, которая приводит к созданию неверных контрольных сумм для пакетов поддержки активности tcp, имеющих временные метки tcp (но, очевидно, для других пакетов), См. Тему в списке сетевых устройств .Этот вопрос должен быть закрыт.

Ответы [ 4 ]

5 голосов
/ 13 июня 2011

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

1 голос
/ 11 января 2012

Мы столкнулись с этой же проблемой у моего нынешнего работодателя. Мы случайно обнаружили, что если на сервере Windows 2008 R2 для «Состояние разгрузки дымохода» установлено значение «Включено», то такое же отключение происходит через 40 секунд. Если для этого параметра установлено значение «Автоматически», то оно работало просто отлично.

1 голос
/ 18 июля 2011

Я видел аналогичную проблему с Windows Server 2003 и сервером SQL, имеющими отношение к Scalable Networking Pack (SNP) на компьютере, на котором установлен сетевой адаптер с поддержкой разгрузки TCP / IP.

Информация и решение здесь:

http://support.microsoft.com/kb/948496

0 голосов
/ 29 июня 2016

Мы видим ту же проблему, когда проблема возникла, "Состояние разгрузки дымохода" установлено на Включено, но должно быть отключено.

Основная причина, которую мы обнаружили, была: один из семантических патчей, примененных на сервере, сбросил этот флаг на Включено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...