Тайм-аут SQL-сервера 2000 из С# .NET

Я столкнулся со странной проблемой при использовании SQL Server 2000 и двух связанных серверов. Вот уже два года наше решение работает без сбоев, но вчера внезапно истекло время ожидания запроса на синхронизацию данных из одной базы данных в другую.

Я подключаюсь к серверу в производственной сети, который связан с сервером, содержащим заказы, данные с которых мне нужны.

Запрос содержит несколько объединений, но в основном это суммирует то, что делается:

INSERT INTO ProductionDataCache
   (column1, column2, ...)
   SELECT tab1.column1, tab1.column2, tab2.column1, tab3.column1 ...
       FROM linkedserver.database.dbo.Table1 AS tab1
       JOIN linkedserver.database.dbo.Table2 AS tab2 ON (...)
       JOIN linkedserver.database.dbo.Tabl32 AS tab3 ON (...)
       ...
       WHERE tab1.productionOrderId = @id
       ORDER BY ...

Очевидно, моей первой попыткой решить проблему было увеличение тайм-аута с первоначальных 5 минут. Но когда я приехал на 30-й минуте и все же получил тайм-аут, я начал подозревать, что происходит что-то еще. Запрос просто не переходит от выполнения менее чем за 5 минут до более чем 30 минут за ночь.

Я вывел SQL-запрос (который изначально был в коде C#) в свои журналы и решил выполнить запрос в Query Analyzer непосредственно на сервере базы данных. К моему большому удивлению, запрос выполнился правильно менее чем за 10 секунд.

Поэтому я изолировал выполнение SQL в простой тестовой программе и наблюдал одинаковое время ожидания запроса как на сервере, на котором изначально выполнялось это решение, так и при его локальном запуске на сервере базы данных. Также я попытался создать хранимую процедуру и выполнить ее из программы, но это также истекло. Запуск его в Query Analyzer работает нормально менее чем за несколько секунд.

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

ОБНОВЛЕНИЕ: теперь я использовал SQL Profiler на сервере. Очевидная разница заключается в том, что при выполнении запроса из программы .NET он отображается в журнале как «exec sp_executesql N'INSERT INTO...'», но при выполнении из Query Analyzer он отображается в журнале как обычный запрос. .

Далее я попытался подключить SQL Query Analyzer, используя того же пользователя SQL, что и программа, и это вызвало проблему и в Query Analyzer. Таким образом, проблема возникает только при подключении через TCP/IP с использованием пользователя sql.


person Johnny Egeland    schedule 19.01.2010    source источник
comment
Убедились ли вы, что какие-либо логины, выполняющие этот код, не заблокированы и не изменили домены? Кроме того, это больше похоже на проблему безопасности, чем на что-либо еще. Как работает программа под какой учетной записью?   -  person JonH    schedule 19.01.2010
comment
Я попытался выполнить простой запрос SELECT COUNT(*) только для того, чтобы убедиться, что программа действительно взаимодействует с сервером БД и может получить от него какие-либо результаты. Это сработало нормально.   -  person Johnny Egeland    schedule 19.01.2010


Ответы (1)


Есть несколько вещей, которые нужно исследовать; первый — SET вариантов; это может иметь огромное значение для некоторых запросов. Посмотрите на параметры SET в трассировке и повторите их при тестировании в Management Studio (или Query Analyzer). Обратите внимание, что для того, чтобы действительно увидеть их, вам придется просмотреть реальный сеанс профиля (а не только то, что регистрирует ваш код).

Следующее, на что я бы обратил внимание, это транзакции; какую модель транзакций вы используете в своем С#? Любой? Никто? Какая изоляция? Сериализуемый? Может раздали? Возможно, на столе держится какой-то непонятный замок.

Конечно, если блокировка является проблемой, вы можете увидеть что-то через sp_who/sp_who2 во время выполнения запроса.

person Marc Gravell    schedule 19.01.2010