Как предотвратить «истечение тайм-аута запроса»? (Ошибка SQLNCLI11 '80040e31')
У меня есть подключение к базе данных MS SQL Server 2012 в классическом ASP (VBScript). Это моя строка подключения:
Provider=SQL Server Native Client 11.0;Server=localhost; Database=databank;Uid=myuser;Pwd=mypassword;
Когда я выполняю эту команду SQL:
UPDATE [info] SET [stamp]='2014-03-18 01:00:02', [data]='12533 characters goes here', [saved]='2014-03-18 01:00:00', [confirmed]=0,[ip]=0,[mode]=3,[rebuild]=0, [updated]=1,[findable]=0 WHERE [ID]=193246;
Я получаю следующую ошибку:
- Объявить значение из CSV для запроса SQLCMD
- Запрошенной операции требуется объект сеанса OLE DB, который не поддерживается текущим поставщиком
- Невозможно избежать дубликатов, используя инструкцию IF NOT EXIST
- Как скопировать из базы данных в текстовый файл с помощью VBScript?
- ADODB.Recordset: операция не разрешается, когда объект закрыт
Microsoft SQL Server Native Client 11.0 error '80040e31' Query timeout expired /functions.asp, line 476
SQL-запрос довольно длинный, поле данных обновляется с 12533 символами. Столбец идентификатора индексируется, поэтому поиск сообщения с идентификатором 193246 должен быть быстрым.
Когда я выполняю то же самое выражение SQL (скопированное и вставленное) в SQL Server Management Studio, оно завершается успешно в кратчайшие сроки. Нет проблем, что так было. Таким образом, проблема с самим SQL не возникает. Я даже попытался использовать объект ADODB.Recordset и обновить его (без самозанятого SQL), но я все равно получаю ту же ошибку тайм-аута.
Если я перейду в «Инструменты»> «Параметры»> «Выполнение запросов» в Management Studio, я вижу, что время выполнения для выполнения установлено на 0 (бесконечное). В разделе «Инструменты»> «Параметры»> «Дизайнеры» я вижу, что время транзакции установлено равным 30 секундам, чего должно быть достаточно много, так как сценарий и база данных находятся на одном компьютере («localhost» находится в строке подключения).
Что здесь происходит? Почему я могу выполнить SQL в Studio Management, но не в моем ASP-коде?
Edit: Пробовал установить тайм-аут 30 секунд на вкладке «Дизайнеры» на 600 секунд, чтобы убедиться, но я все равно получаю ту же ошибку (происходит через 30 секунд загрузки страницы по btw).
Вот код, который я использую для выполнения SQL на странице ASP:
Set Conn = Server.CreateObject("ADODB.Connection") Conn.Open "Provider=SQL Server Native Client 11.0; Server=localhost;Database=databank;Uid=myuser;Pwd=mypassword;" Conn.Execute "UPDATE [info] SET [stamp]='2014-03-18 01:00:02', [data]='12533 characters goes here',[saved]='2014-03-18 01:00:00', [confirmed]=0,[ip]=0,[mode]=3,[rebuild]=0,[updated]=1,[findable]=0 WHERE [ID]=193246;"
Редактирование 2: Использование Conn.CommandTimeout = 0
для предоставления бесконечного времени выполнения запроса ничего не делает, это просто заставляет запрос выполнять навсегда. Ждал 25 минут, и он все еще исполнялся.
Затем я попытался разделить SQL на два оператора SQL, длительное обновление данных в одном и других обновлениях в другом. Он по-прежнему не будет обновлять длинное поле данных, просто получил таймаут.
Я попробовал это с двумя дополнительными строками подключения:
Driver={SQL Server};Server=localhost;Database=databank;Uid=myuser;Pwd=mypassword; Driver={SQL Server Native Client 11.0};Server=localhost;Database=databank;Uid=myuser;Pwd=mypassword;
Не работает. Я даже попытался сменить данные на 12533 А, чтобы проверить, не привели ли фактические данные к этой проблеме. Нет, та же проблема.
Затем я узнал что-то интересное: сначала я попытался выполнить короткий SQL, перед длинным обновлением поля данных. Он также получил исключение тайм-аута запроса …
Но почему? В нем так мало материала для обновления (весь оператор SQL составляет менее 200 символов). Будут исследовать дальше.
Редактировать 3: Я думал, что это могло быть связано с логином, но я не нашел ничего, что выглядело бы неправильно. Я даже попытался изменить строку подключения для использования sa-account, но даже это не сработало, все еще получая «Истекло время ожидания запроса».
Это сводит меня с ума. Нет решения, нет обходного пути и хуже всего нет идей!
Редактирование 4: Пошли в Инструменты> Параметры> Дизайнеры в Studio Management и отметили «Запретить сохранение изменений, требующих повторного создания таблицы». Он ничего не сделал.
Попробовал сменить тип данных столбца данных «данные» с «nvarchar (MAX)» на более низкий тип «ntext» (я отчаянно). Это не сработало.
Пытался выполнить наименьшее изменение на посту, о котором я мог подумать:
UPDATE [info] SET [confirmed]=0 WHERE [ID]=193246;
Это установило бы бит столбца в значение false. Не работает. Я попытался выполнить тот же самый запрос в Management Studio, и он работал безупречно.
Бросьте мне некоторые идеи, если у вас их есть, потому что я бежаю сейчас.
Изменить 5: теперь также попробовали следующую строку подключения:
Provider=SQLOLEDB.1;Password=mypassword;Persist Security Info=True;User ID=myuser;Initial Catalog=databank;Data Source=localhost
Не работает. Только попытался установить подтвержденным, но все же получил тайм-аут.
Изменить 6: теперь попытались обновить другую запись в той же таблице:
UPDATE [info] SET [confirmed]=0 WHERE [ID]=1;
Он также дал ошибку тайм-аута. Итак, теперь мы знаем, что это не почта специфическая.
Я могу обновлять сообщения в других таблицах в той же базе данных «базы данных» через ASP. Я также могу обновлять таблицы в других базах данных на localhost.
Может быть что-то сломано с таблицей [info]? Я использовал мастер доступа MS для автоматического перемещения данных из Access в MS SQL Server 2012, он создал столбцы типа данных «ntext», и я вручную перешел и изменил это на «nvarchar (MAX)», поскольку ntext устарел. Разве что-то сломалось? Это потребовало от меня повторного создания таблицы, когда я изменил тип данных.
Мне нужно немного поспать, но я обязательно вернусь завтра, если кто-нибудь ответит мне. Пожалуйста, сделайте это, даже если у вас есть только что-то обнадеживающее.
Редактирование 7: Быстрое редактирование перед сном. Пытался определить провайдера как «SQLNCLI11» в строке соединения (используя имя DLL вместо фактического имени поставщика). Это не имеет значения. Соединение создается так же хорошо, но тайм-аут все же происходит.
Также я не использую MS SQL Server 2012 Express (насколько я знаю, «Экспресс» нигде не упоминался во время установки). Это все.
Если это помогает, вот информация «Справка»> «О …», которую предоставляет Management Studio:
Microsoft SQL Server Management Studio: 11.0.2100.60 Microsoft Analysis Services Client Tools: 11.0.2100.60 Microsoft Data Access Components (MDAC): 6.3.9600.16384 Microsoft MSXML: 3.0 5.0 6.0 Microsoft Internet Explorer: 9.11.9600.16521 Microsoft .NET Framework: 4.0.30319.34011 Operating System: 6.3.9600
Edit 8 (также известный как «программисты никогда не спят»):
Попробовав некоторые вещи, я в конце концов попытался закрыть соединение с базой данных и снова открыть ее перед выполнением операторов SQL. Это сработало неожиданно. Что за…?
У меня был код внутри подпрограммы, и выяснилось, что за его пределами сообщение, которое я пытался обновить, уже было открыто! Поэтому причиной таймаута было то, что столбец или целая таблица были заблокированы тем же самым соединением, которое пыталось его обновить . Таким образом, соединение (или поток ЦП) ожидало блокировки, которая никогда не будет разблокирована.
Ненавидите его, когда он окажется таким простым после того, как вы так стараетесь.
Этот пост был открыт за пределами подпрограммы:
Set RecSet = Conn.Execute("SELECT etc")
Я просто добавил следующее, прежде чем вызвать подпрограмму.
RecSet.Close Set RecSet = Nothing
Причина, по которой это никогда не приходило мне в голову, просто потому, что это разрешалось в MS Access, но теперь я изменился на MS SQL Server, и это было не очень мило (или неаккуратно, скорее). Созданный RecSet by Conn.Execute () никогда ранее не создавал заблокированную запись в базе данных, но теперь это внезапно. Не слишком странно, потому что строка подключения и фактическая база данных изменились.
Я надеюсь, что этот пост спасет кого-то еще от головной боли, если вы перейдете с MS Access на MS SQL Server. Хотя я не могу себе представить, что в настоящее время многие пользователи Access остаются в мире.
- Как вернуть COUNT (*) и сохранить его в переменной для дальнейшего использования в VBscript
- ASP VBscript получает sql-скрипт хранимой процедуры
- Агент SQL и запуск SSIS в сети не работает
- SSIS, как я могу вставить пустую дату в базу данных с визуальным базовым
- Как я могу в классическом ASP / VBScript получить значение переменной с SET @local_variable?
- Ошибка параметра ADO в VBScript
- Параметр команды ADO не переходит к хранимой процедуре или хранимой процедуре «Игнорирование» параметра
- UFT: состояние ADODB закрыто при выполнении SQL
Оказывается, что сообщение (или, скорее, целая таблица) было заблокировано тем же соединением, которое я пытался обновить.
У меня был открытый набор записей, который был создан:
Set RecSet = Conn.Execute()
Этот тип записей должен быть доступен только для чтения, и когда я использовал MS Access в качестве базы данных, он ничего не блокировал. Но, по-видимому, этот тип набора записей заблокировал что-то на MS SQL Server 2012, потому что, когда я добавил эти строки кода перед выполнением инструкции UPDATE SQL …
RecSet.Close Set RecSet = Nothing
… все работало отлично.
Поэтому нижняя строка должна быть осторожна с открытыми наборами записей – даже если они доступны только для чтения, они могут заблокировать вашу таблицу от обновлений.