2017-02-22 27 views
1

Я работаю с интерфейсом Access 2007, связанным с бэкэнд SQL Server 2008 R2, и столкнулся с тем, что, по моему мнению, является странным действием блокировки, вызванным даже простыми поисковыми запросами. Более конкретно:MS Access passthrough select запрос, вызывающий блокировку страницы в SQL Server

У меня есть транзитный запрос простой формы «SELECT * FROM tbl_A». Если я открою этот запрос в доступе (просмотр запроса в стандартном представлении данных), и в таблице будет достаточно много записей (примерно> 100 записей, я не экспериментировал, чтобы найти точную привязку), тогда я получаю блокировку этой таблицы в SQL Server для пока я держу запрос открытым. Если я попытаюсь запустить запрос на обновление или что-то подобное на столе, это приведет к взаимоблокировке. То же самое происходит, если я открываю непрерывную форму, которая имеет этот сквозной запрос, заданный как источник записи. Глядя на представление sys.dm_tran_locks в SQL Server показывает, что это блокировка IS на странице данных ... не знаю, помогает ли это. Как только я нажму кнопку «Последняя запись» в разделе «Доступ», чтобы перейти к концу запроса или формы, блокировка будет удалена, а другие мои процессы снова смогут обновить таблицу.

Насколько я могу видеть, мои свойства формы и/или запроса установлены в их значения по умолчанию (тип набора записей = dynaset, блокировка записи = блокировки). На основе описания динасетов, например, приведенный здесь: https://msdn.microsoft.com/en-us/library/bb188204.aspx Я бы ожидал, что он загрузит только небольшие партии данных, необходимые для заполнения области просмотра, без блокировки сервера в течение длительного периода времени. Как связана статья говорит:

Потому что они работают только несколько строк, в то время, динамические подмножества минимизировать продолжительности, что читать блокировки удерживаются на сервере. Это позволяет другим пользователям изменять данные без необходимости ждать столько, сколько необходимо для блокировки для очистки.

Может ли кто-нибудь объяснить, почему dynaset работает не так, как ожидалось?

Я видел несколько возможных обходных решений, например.

  • используя NOLOCK подсказки (как это было предложено здесь MS Access holds locks on table rows indefinitely, но мне кажется, NOLOCK не рекомендуется вообще?)
  • с помощью отключенного набора записей ADO как recordsources для моих форм
  • тянущих данные с сервера в временные таблицы на стороне клиента и основываясь на тех временных таблицах
  • перепроектируйте интерфейс, добавьте ограничители и т. д., чтобы формы никогда не тянули больше, чем 100 записей (было бы много работы и казалось бы небезопасным без гарантии, что оно будет никогда не блокировать с указанным количеством записей)

Все эти предложения либо не работают для меня, либо, похоже, имеют много других недостатков и/или требуют серьезного перезаписи интерфейса ... Каков наилучший способ обойти эту проблему?

+0

У вашей базовой таблицы на SQL Server есть уникальный кластеризованный индекс? Не имея возможности вводить определенные проблемы, хотя и не обязательно это. У вас есть возможность использовать проект Data Access Project? Затем вы можете использовать OLEDB вместо ODBC ... – mroach

+0

Вы пытались изменить привязанную таблицу к режиму моментального снимка? Было бы интересно узнать, изменит ли это поведение. – mroach

+0

Спасибо за комментарии @mroach. Да, таблица имеет уникальный кластеризованный индекс. Моя проблема возникает даже при использовании чистого запроса-транзита (без связанной таблицы), я не уверен, что вы подразумеваете под «привязанной таблицей к режиму моментального снимка». Я попытался изменить форму «тип набора записей» на моментальный снимок, но это ничего не меняет. – Maxbromo

ответ

2

После покопаться и экспериментировать дальше, я вижу это так:

С настройками по умолчанию на SQL Server, то Dynaset из Access действительно поддерживает блокировку чтения, пока она не будет полностью загружена все данные. Это необходимо для предотвращения несовместимых чтений, иначе могут возникнуть другие транзакции и изменить порядок данных между последующими «пакетами» выталкиваемого динамика, что может привести к удалению повторяющихся строк или пропущенных строк. (аналогично тому, что может произойти с запросом NOLOCK, если страница SQL Server перестраивается во время выполнения запроса).

Так что, кажется, только два пути, чтобы избежать этого:

1) сил доступа к «полному» запросу, используя моментальный снимок, а не динамический набора или делать какое-то «движение последние» операций на dynaset или убедитесь, что оператор select возвращает только так мало записей, что Access будет загружать их все сразу.

2) предотвратить блокировки чтения, используя подсказки NOLOCK или установив READ_COMMITTED_SNAPSHOT ON в базе данных SQL Server.

Мы собираемся перейти с параметром READ_COMMITTED_SNAPSHOT ON, поскольку это означает, что во внешнем интерфейсе ничего не нужно менять, и в любом случае я обычно предпочитаю не блокировать операции записи при выполнении операции чтения.