Тайм-аут запроса при запуске t-sql операторов сохранения или обновления, скомпилированных в vba и запущенных в SQL Server
Моя компания в настоящее время работает на SQL Server 2000 и собирается перейти на SQL Server 2012, но прежде чем мы перейдем к обновлению, мы хотим попытаться устранить проблему производительности, которая недавно возникла и мешает нашей способности вести бизнес.,
Несколько месяцев назад мы решили, что хотим добавить текстовое поле в одну из наших таблиц sql server, чтобы попытаться зафиксировать определенное событие. Я думал, что попробую добавить столбец в течение дня, что, вероятно, было первой ошибкой, но я решил, что если люди будут использовать таблицу, SQL Server не позволит мне добавить столбец. При этой попытке дополнительный столбец был принят и добавлен в таблицу. Затем я закодировал наш интерфейс доступа для записи в этот новый столбец.
Вскоре после этого пользователи начали испытывать "зависание" в графическом интерфейсе Access и в конечном итоге выдавали ошибку времени ожидания запроса.
Вот как происходит ошибка. После нажатия кнопки "Сохранить" в клиентской части Access, которая затем создаст оператор V-SQL в VBA для обновления или сохранения новой записи, пользователи не увидят окно сообщения Access, сообщающее, что сохранение завершено успешно или произошла ошибка., Вместо этого они получат диалоговое окно системы доступа, в котором будет указано, что время запроса истекло. На этот раз я удалил добавленную колонку, надеясь, что это решит проблему.
Я начал анализ с того, что все закрыли свою программу доступа, а затем попросили человека, у которого возникли проблемы, открыть заново и попытаться снова сохранить. Это сработало для этого пользователя, и я позволил бы всем остальным вернуться в систему в это время. Конечно, я не был уверен, почему это сработало в то время, поэтому я попытался разобраться в этом вопросе. Дальнейший анализ привел меня к sp_who2. Запуск этого даст мне всех пользователей и SPID того, кто блокировал. Это дало мне более быстрый способ заставить все работать снова, потому что я мог убить обидчивый SPID и позволить всем остальным продолжать работать. Конечно, уничтожение приводит к откату, поэтому не все данные сохраняются, и я должен сказать владельцу уничтоженного процесса, что он должен повторно ввести все свои данные во второй раз. На сегодняшний день я постоянно отслеживаю эту базу данных таким образом, и если я нахожу что-то заблокированным, я так и исправляю.
Я знаю, что проблема с одной таблицей в этой базе данных, во-первых, проблема возникла только после того, как я попытался ввести новый столбец, но также и потому, что каждый раз, когда выполняется сохранение или обновление, она блокируется при записи в эту конкретную таблицу. В то время я диагностировал это, потому что я спросил своих пользователей, какое действие они пытаются выполнить, и во всех случаях они пытались что-то сделать с этой конкретной таблицей. Фактически, изменения в других таблицах в этом же БД выполняются без проблем. Поэтому я чувствовал, что проблема может быть связана с коррупцией в этой таблице.
Первым делом я запустил CHECKDB и CHECKTABLE, но ни один из них не привел к возникновению проблемы с таблицей. Поэтому мы решили восстановить таблицу. Я восстановил таблицу вручную, затем скопировал данные из исходной таблицы в новую таблицу. Я полагаю, что я использовал инструмент SQL для этого, но я, возможно, запустил вставку. (Это было давно, и я не документировал.) В любом случае, это не сработало. Организация продолжала испытывать блокировку. Затем я переиндексировал таблицу, и это, казалось, сработало около суток, а затем ошибка "вернулась". С тех пор я обнаружил INPUTBUFFER, который я запускал на SPID блокирующего пользователя каждый раз для в то время как. Почти каждый раз INPUTBUFFER возвращал инструкцию SELECT, хотя я не думаю, что это было то, что бросало блок. Я не думаю, что SELECT выбрасывал блок, потому что в Access GUI происходит то, что вы нажимаете кнопку "Сохранить", он запускает сохранение или обновление, а затем запускает команду выбора, чтобы обновить экран доступа. Я бы подумал, что если бы SELECT выбрасывал блок, то произойдет сохранение, но при вызове записи после того, как процесс начинает блокироваться, и процесс завершается, изменения пользователя никогда не сохраняются в записи. Я не совсем уверен, как работает INPUTBUFFER. Я знаю, что он предположительно возвращает последний оператор, отправленный на SQL Server, но если сохранение не зафиксировано, может ли Access по-прежнему отправлять SQL на SQL Server?
Я также добавлю, что я никогда не бросаю блок, когда работаю в самой SQL Server Management Studio. Я, очевидно, почувствовал последствия существующего блока, который повесит мой SQL-оператор, но я никогда не бросал блок, насколько мне известно. С этой целью я также обновил соединители ODBC от каждого пользователя до 10.0. Похоже, это не оказывает негативного или положительного влияния на проблему.
Так что я не уверен, что делать дальше. Мы ценим любые предложения.
1 ответ
При работе со связанными таблицами убедитесь, что ваша таблица SQL Server имеет уникальный идентификатор.
Проверьте мою статью о том, как связать таблицы.
Второй вопрос: какой тип блокировки вы получаете?
Ниже приведен код из презентации, которую я делаю время от времени. Измените adventureWorks2012 на имя вашей базы данных.
Это должно показать вам, какие блокировки происходят. Выберите правильный hobt_id или object_id, чтобы узнать подробности.
--
-- Locked object details
--
-- Old school technique
EXEC sp_lock
GO
-- Lock details
SELECT
resource_type, resource_associated_entity_id,
request_status, request_mode,request_session_id,
resource_description
FROM sys.dm_tran_locks
WHERE resource_database_id = DB_ID('AdventureWorks2012')
GO
-- Page/Key details
SELECT object_name(object_id) as object_nm, *
FROM sys.partitions
WHERE hobt_id = 72057594047037440
GO
-- Object details
SELECT object_name(1266103551)
GO
Блокировка является частью того, как SQL-сервер обеспечивает совместное выполнение между сеансами. Проблема в том, что он превращается в тупик или SQL-сервер не обнаруживает тупик.
Некоторые решения должны изменить уровень изоляции. Но у этого есть свои проблемы - фантомное чтение, грязное чтение, неповторимое чтение и низкий уровень параллелизма. Первое, что нужно посмотреть, это последовательность блокировки. Пожалуйста, разместите изображение.
Поскольку вы используете SQL Server 2000, посмотрите на sp_indexoption.
Обзор:
http://technet.microsoft.com/en-us/library/aa213036(v=sql.80).aspx
"Например, когда известно, что таблица является предметом спора, может быть полезно запретить блокировки на уровне страницы, тем самым разрешив только блокировки на уровне строк. Или, если сканирование таблицы всегда используется для доступа к индексу или таблице, Запрет блокировки на уровне страницы и на уровне строки может помочь, разрешив только блокировки на уровне таблицы."
Подробности:
http://technet.microsoft.com/en-us/library/aa238800(v=sql.80).aspx
Попробуйте остановить программу MS Access от использования блокировок страницы.
Пример звонка от BOL:
USE Northwind
GO
EXEC sp_indexoption 'Customers.City',
'disallowpagelocks',
TRUE
GO
Используйте sp_who2, чтобы получить два SPIDS, которые блокируют.
Используйте DBCC INPUTBUFFER, чтобы получить фактический оператор SQL для обоих SPIDS.