Тайм-ауты доступа 2000 на связанном наборе записей

Взрыв из прошлого... У меня была задача управлять устаревшим приложением Access 2000, используемым для управления данными, находящимися на сервере SQL 2005. На одной из форм данных каждый раз, когда я пытаюсь внести изменение в поле и сохранить его обратно в базе данных, оно истекает примерно через минуту. Увеличение лимита времени ожидания только задерживает отображение сообщения об ошибке времени ожидания. Я прошел все обычные способы устранения неполадок, чтобы обеспечить совместимость (см., Например, этот вопрос SO).

Это настройка: форма связана с набором записей (который читается из базы данных как SELECT * FROM table_name запрос. Размер результирующего набора варьируется в зависимости от фильтров, установленных в форме, но обычно получается около 200 записей (не много данных...). Некоторые поля формы запускают автоматическое сохранение в связанном обработчике событий, который выглядит примерно так:

Private Sub EndDate_Exit(Cancel As Integer)
     some checking goes here...
     ...
     DoCmd.RunCommand acCmdSaveRecord
End Sub

Всякий раз, когда DoCmd.RunCommand acCmdSaveRecord код выполняется, ADP зависает, пока я не получу ошибку тайм-аута. Углубившись в это немного глубже, я посмотрел на Activity Monitor на SQL Server. acCmdSaveRecord вызывает UPDATE выписка на сервер для сохранения измененных данных. Сам оператор автоматически создается MS Access на основе первичного ключа базовой таблицы, который, по-видимому, определен правильно. Тем не менее, обновление заблокировано работающим SELECT утверждение, которое соответствует SELECT * FROM table_name запрос, упомянутый выше.

Это приводит к тупику: изменение пользователя вызывает UPDATE, который заблокирован бегом SELECT (которая, как представляется, возникла из редактируемой формы). Как я могу обойти это?

Вещи, которые мы попробовали:

  1. Мы удалили DoCmd.RunCommand acCmdSaveRecord заявление и заменил его с кодом Me.Dirty = False, что приводит к точно такому же поведению, как описано выше.
  2. Удалил acCmdSaveRecord завершить и использовать встроенное меню доступа, чтобы сохранить изменения. Эта функциональность эквивалентна #1 и ведет к точно такому же поведению.
  3. Заменить acCmdSaveRecord вызов с хранимой процедурой, которая сохраняет изменения в определенном поле. Прекрасно работает, за исключением того, что сохранение всей записи из графического интерфейса (кнопка сохранения, которая вызывает acCmdSaveRecord) приводит к тому же тупику.
  4. Уменьшен размер результирующего набора, связанного с формой, до нескольких записей. Как ни странно, все еще демонстрирует ТОЧНО такое же поведение.

1 ответ

Решение

Звучит так, как будто вы установили уровень изоляции транзакции на SERIALIZABLE для вашего подключения в какой-то момент. См. SET SET TRANSACTION ISOLATION LEVEL (Transact-SQL) для более подробной информации. Вот соответствующая выдержка (выделение добавлено):

SERIALIZABLE

Определяет следующее:

  • Операторы не могут читать данные, которые были изменены, но еще не зафиксированы другими транзакциями.

  • Никакие другие транзакции не могут изменять данные, которые были прочитаны текущей транзакцией, пока текущая транзакция не завершится.

  • Другие транзакции не могут вставлять новые строки со значениями ключей, которые попадают в диапазон ключей, считываемых любыми операторами в текущей транзакции, пока текущая транзакция не завершится.

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

Другие вопросы по тегам