Справка по устранению неполадок SQLException:Тайм-аут истек при подключении в ситуации без загрузки

StackOverflow https://stackoverflow.com/questions/1421978

Вопрос

У меня есть сервер, на котором размещен мой веб-сайт с почти нулевым трафиком.
Несколько человек (< 20) заходите на сайт каждый день, и несколько читателей RSS подписаны на некоторые каналы, которые мы публикуем.

Почти каждую ночь к нам посреди ночи приходит программа для чтения RSS и выдает исключение о том, что веб-сайт не может подключиться к SQL Server из-за тайм-аута в соединении.Детали чрезвычайно странные, поэтому я ищу некоторую помощь в том, в чем может быть проблема, поскольку я больше не знаю, с чего начать поиски.

Мы используем ASP.Net MVC, Entity Framework и SQL Server 2008 поверх Windows Server 2008.Аппарат представляет собой выделенную коробку, которую мы получили от поставщика не самого высокого уровня, поэтому все может быть настроено неоптимально или, кто знает, что еще.
Коробка также довольно маленькая и имеет всего 1 Гб оперативной памяти, но она должна выдерживать ту нагрузку, которая у нас есть на данный момент...

Я копирую полный стек вызовов ниже, но сначала некоторые из вещей, которые мы знаем:

  • Ошибка всегда возникает, когда iTunes запрашивает наш сайт.Я считаю, что это не должно иметь никакого отношения ни к чему, но правда в том, что мы получаем это только из iTunes.Мое лучшее предположение заключается в том, что это происходит потому, что только iTunes запрашивает нас в то время ночи, когда никто другой нас не бьет.
  • Одна из наших теорий заключается в том, что SQL Server и IIS борются за память, и одна из них заключается в том, что они выгружаются на диск из-за неиспользования, и когда кто-то "пробуждает его", требуется слишком много времени, чтобы прочитать все с диска обратно в память.Это то, что потенциально может произойти?(Я как бы отбрасываю это, поскольку это звучит как проблема дизайна в SQL Server, если бы это было возможно)
  • Я также подумал о возможности утечки соединений, поскольку мы, возможно, не утилизируем объекты EF надлежащим образом (смотрите мой вопрос здесь).Это единственное, что я смог найти, погуглив проблему.Я отказываюсь от этого, учитывая нашу чрезвычайно низкую нагрузку.
  • Это всегда происходит ночью, так что, скорее всего, это как-то связано с тем фактом, что некоторое время ничего не происходило.Например, я почти уверен, что при поступлении этих запросов процесс веб-сервера был переработан, и он все запускает / перезаписывает.Однако повторная настройка не объясняет тайм-аут SQL.

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

  • Наличие подключенного профилировщика чрезвычайно уменьшилось количество ошибок, которые мы получали.На самом деле, после обычного получения нескольких таблеток в день, нам пришлось ждать 3 или 4 дня, чтобы это произошло ОДИН РАЗ.Как только мы остановили профилировщик, он вернулся к нормальной частоте ошибок (или даже хуже).Таким образом, профилировщик имеет некоторые эффект, который в некоторой степени скрывает эту проблему, но не полностью.
  • Просматривая трассировку профилировщика рядом с журналом запросов IIS, можно увидеть ожидаемое соответствие 1-1 между запросами и queries .Однако время от времени я вижу множество выполняемых запросов, которые вообще не имеют корреляции с журналом IIS.На самом деле, прямо перед тем, как была зарегистрирована фактическая ошибка, я получил 750 запросов в течение 3 минут, все из которых были совершенно не связаны с журналами IIS.Текст запроса выглядит как нечитаемая чушь, которую генерирует EF, и не все они одинаковы, и все они выглядят точно так же, как запросы, поступающие с веб-сайта:То же имя приложения, Пользователь и т.д.Чтобы дать представление о том, насколько это нелепо, сайт получил около 370 запросов IIS, которые попали в базу данных, в ходе 2 дня
  • Эти необъяснимые запросы исходили не из того же ClientProcessID, что и предыдущие запросы веб-сайта, хотя они все еще могли поступать с веб-сайта, если за это время процесс был переработан.Между последним объясненным запросом и первым необъяснимым прошел почти час без какой-либо активности.
  • Одна из этих длинных цепочек запросов, которые я не знаю, откуда они взялись, появилась прямо перед ошибкой, которую я зарегистрировал, поэтому я считаю, что это подсказка, которой мы должны следовать.
  • Как я и ожидал изначально, когда запрос, выдавший ошибку, был выполнен, он пришел с другого ClientProcessID, чем предыдущий (на 8 минут позже, чем предыдущий необъяснимый, и почти ровно на час позже, чем предыдущий IIS).Для меня это означает, что рабочий процесс действительно был переработан.
  • Это то, чего я абсолютно не понимаю.Журнал IIS показывает, что за минуту до запросов с ошибкой 4 были обработаны идеально, хотя запросы для них вообще не отображаются в трассировке.Фактически, после тех 4, которые прошли хорошо, у меня было 4 исключения, выданных в быстрой последовательности, эти 4 ТАКЖЕ не отображаются в трассировке (что имеет смысл, поскольку, если в соединении был тайм-аут, запрос никогда не должен был выполняться, но я также не вижу попыток подключения в трассировке)

Итак, короче говоря, я совершенно ничего не понимаю в этом.Я не могу найти причину для тех сотен запросов, которые выполняются в быстрой последовательности, но я считаю, что они должны иметь какое-то отношение к проблеме.
Я также не знаю, как диагностировать проблемы с подключением...
Или как в трассировке Профилировщика могут отсутствовать некоторые запросы, которые, согласно IIS, прошли нормально...

Есть какие-нибудь идеи?


Это информация об исключении:

System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

System.Data.EntityException: The underlying provider failed on Open. ---> System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   --- End of inner exception stack trace ---
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   at System.Data.EntityClient.EntityConnection.Open()
   at System.Data.Objects.ObjectContext.EnsureConnection()
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__1[TResult](IEnumerable`1 sequence)
   at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
   at MyProject.Controllers.SitesController.Feed(Int32 id) in C:\...\Controller.cs:line 38
   at lambda_method(ExecutionScope , ControllerBase , Object[] )
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Любые идеи будут высоко оценены.

Это было полезно?

Решение

Недостаточно памяти

Скорее всего, это проблема с памятью, возможно, усугубленная или вызванная другими причинами, но все же по своей сути это проблема с памятью.есть две другие (менее вероятные) возможности, которые вы должны сначала проверить и исключить (потому что это легко сделать).:

Легко Проверяемые Возможности:

  1. Возможно, у вас включено "Автоматическое закрытие":Автоматическое закрытие может иметь именно такое поведение, однако оно редко включается.Чтобы проверить это, в SSMS щелкните правой кнопкой мыши на базе данных вашего приложения, выберите "Свойства", а затем выберите панель "Параметры".Посмотрите на запись "Автоматическое закрытие" и убедитесь, что для нее установлено значение False.Проверьте также базу данных tempdb.

  2. Причиной этого могут быть задания агента SQL:Проверьте журнал истории агента, чтобы узнать, выполнялись ли какие-либо задания последовательно во время событий.Не забудьте также проверить задания по обслуживанию, поскольку такие вещи, как перестройка индексов, часто упоминаются как проблемы с производительностью во время их выполнения.Сейчас это маловероятные кандидаты только потому, что Профилировщик обычно не влияет на них.

Почему Это Похоже На Проблему с памятью:

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

  • У вас есть 1 ГБ оперативной памяти:Хотя технически это выше Минимума для SQL Server, это намного ниже рекомендуемого для SQL Server и намного ниже того, что, по моему опыту, приемлемо для производства, даже для слегка загруженного сервера.

  • Вы запускаете IIS и SQL Server в одном и том же окне:Само по себе это не рекомендуется, в значительной степени из-за возникающей конкуренции за объем памяти, но при использовании всего 1 ГБ памяти это приводит к тому, что IIS, приложение, SQL Server, ОС и любые другие задачи и / или обслуживание требуют очень мало памяти.Способ, которым Windows справляется с этим, заключается в предоставлении памяти активным процессам путем агрессивного изъятия ее у неактивных процессов.Большому процессу, такому как SQL Server, может потребоваться много секунд или даже минут, чтобы восстановить достаточное количество своей памяти, чтобы иметь возможность полностью обслуживать запрос в этой ситуации.

  • Профилировщик устранил 90% проблемы:Это важный признак того, что проблема, скорее всего, связана с памятью, потому что обычно такие вещи, как Profiler, оказывают именно такое влияние на эту конкретную проблему:задача профилировщика позволяет SQL-серверу просто маленький все время немного активен.Часто этого действия достаточно, чтобы либо исключить его из списка "мусорщиков" ОС, либо, по крайней мере, несколько уменьшить его влияние.

Как проверить наличие памяти в качестве Виновника:

  1. Выключите Профилировщик:Это оказывает на проблему эффект Гейзенберга, поэтому вам нужно отключить его, иначе вы не сможете надежно увидеть проблему.

  2. Запустите системный монитор (perfmon.exe) из другого окна, которое удаленно подключается к службе сбора производительности в окне, на котором запущены ваш SQL Server и IIS.проще всего это сделать, сначала удалив три статистики по умолчанию (они только локальные), а затем добавив необходимую статистику (ниже), но обязательно измените имя компьютера в первом раскрывающемся списке для подключения к вашему SQL box.

  3. Отправьте собранные данные в файл, создав "Журнал учета" в perfmon.Если вы не знакомы с этим, то, вероятно, проще всего собрать данные в файл, разделенный табуляцией или запятой, который вы можете открыть с помощью Excel для анализа.

  4. Настройте свой perfmon на сбор данных в файл и добавьте к нему следующие счетчики:

    -- Процессор\% Процессорного времени[Всего]

    -- Время простоя физического диска\%[для каждого диска]

    -- Физический диск \Средний.Длина очереди на диске[для каждого диска]

    -- Объем памяти \Страниц/сек

    -- Память \ Чтение страниц в секунду

    -- Объем памяти \ Доступные МБайты

    -- Сетевой интерфейс \Общее количество байт/сек[для каждого используемого интерфейса]

    -- Процесс\% Процессорного времени[смотрите ниже]

    -- Ошибки процесса \ Страницы /сек[смотрите ниже]

    -- Процесс \ Рабочий набор [смотрите ниже]

  5. Для счетчиков процессов (выше) вы хотите включить процесс sqlserver.exe, любые процессы IIS и любые стабильные прикладные процессы.Обратите внимание, что это будет работать ТОЛЬКО для "стабильных" процессов.Процессы, которые постоянно воссоздаются по мере необходимости, не могут быть зафиксированы таким образом, потому что нет способа указать их до того, как они появятся.

  6. Запустите эту коллекцию в файл в то время, когда проблема возникает чаще всего.Установите интервал сбора данных примерно на 10-15 секунд.(при этом собирается много данных, но вам понадобится это разрешение, чтобы выделить отдельные события).

  7. После возникновения одного или нескольких инцидентов остановите сбор, а затем откройте файл собранных данных с помощью Excel.Вероятно, вам придется переформатировать столбец timestamp, чтобы он был удобно виден и показывал часы, минуты и секунды.Используйте свой журнал IIS, чтобы найти точное время инцидентов, затем просмотрите данные perfmon, чтобы увидеть, что происходило до и после инцидента.В частности, вы хотите посмотреть, был ли его рабочий набор небольшим до и большим после, с большим количеством ошибок страницы между ними.Это самый явный признак этой проблемы.

Решения:

Либо разделите IIS и SQL Server на два разных блока (предпочтительно), либо добавьте в этот блок больше памяти.Я бы подумал, что 3-4 ГБ должно быть как минимум.

А как насчет Этой Странной Ерунды с EF?

Проблема здесь в том, что это, скорее всего, либо второстепенно, либо только усугубляет вашу основную проблему.Помните, что Профилировщик удалил 90% ваших инцидентов, так что же остается, мочь быть другой проблемой, или это может быть только самая крайняя усугубитель о проблеме.Из-за его поведения я бы предположил, что он либо задействует свой кэш, либо выполняет какое-то другое фоновое обслуживание процессов сервера приложений.

Другие советы

Я бы сравнил временную метку тайм-аута со временем выполнения вашего ночного резервного копирования.Если они совпадают, вы могли бы сделать свой RSS-канал статичным на это время.

Еще одна вещь, которую нужно попробовать (даже если это не совсем ответ), - это немедленно запустить sp_ кто когда вы получаете исключение тайм-аута.Он не поймает все (процесс нарушения может быть завершен к моменту, когда вы запустите это), но вам может повезти.

Вы также можете запустить SQL Profiler, когда отправляетесь домой на ночь, и выполнить это действие на следующее утро, если снова увидите ошибку.Просто убедитесь, что не запускаете его с самого сервера (я почти уверен, что он напоминает вам об этом при запуске).

Редактировать: Обращение к вашему обновлению.

Обновляет ли EF / создает ли свой кэш?Это могло бы объяснить обилие запросов за один раз и почему впоследствии ни один запрос не попал в базу данных.

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

Это пахнет коронованной штукой, которая работает в одно и то же время.Как говорит Rbarryyung..какое-нибудь ночное резервное копирование или это может быть что-то другое У вас есть root-доступ к серверу?Ты видишь кронтабы?

Может ли это быть какой-то полнотекстовый плагин индексирования поверх SQL server, который запускает свои процедуры переиндексации непосредственно в то время, когда у вас возникают проблемы?

В моем случае, когда я установил sqlserver 2008 r2 sp3, проблема исчезла.

Сервер: Windows 7 + SQLServer 2008 R2 (версия для разработчиков) клиент: Raspberrypi 3B +,Asp.net Ядро + EF Core

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top