Можно ли создать тупик с доступом только для чтения? - PullRequest
8 голосов
/ 11 мая 2009

У меня есть приложение VB6, которое обращается к одной таблице на сервере MSSQL2000 через ADO. Я использую доступ только для чтения (adOpenStatic, adLockReadOnly) В сети есть другие приложения, которые вносят изменения в таблицу.

По какой-то причине я получаю ошибки о том, что мое приложение выбрано в качестве жертвы тупика.

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

Может кто-нибудь пролить свет на это?

ОБНОВЛЕНИЕ: 2009-06-15 Я все еще заинтересован в решении этой проблемы. Итак, я предоставляю дополнительную информацию:

  • Не имеет значения, если я выберу adOpenForwardOnly или adOpenStatic
  • Не имеет значения, является ли позиция курсора клиентом или сервером.

Ответы [ 8 ]

13 голосов
/ 27 мая 2009

Возможна взаимоблокировка одного оператора SELECT с одним оператором UPDATE или DELETE из-за наличия некластеризованного индекса, рассмотрим следующий сценарий:

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

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

Дополнительную информацию об этом (и другом) тупике можно найти в статье Microsoft KB Q169960 (http://support.microsoft.com/kb/q169960/)

).

Также вы можете посмотреть в Google, как получить информацию о трассировке тупиковой ситуации (флаг трассировки 1222) - здесь будет указано, какие именно операторы SQL конфликтуют с какими объектами при возникновении тупиковой ситуации. Это довольно прилично выглядящая статья - http://blogs.msdn.com/bartd/archive/2006/09/09/747119.aspx

3 голосов
/ 16 июня 2009

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

Ваши общие блокировки несовместимы с другим процессом, использующим эксклюзивные блокировки. Сценарий может запустить что-то вроде этого ...

  1. Вы принимаете общую блокировку на ресурсе A
  2. Другой процесс получает эксклюзивную блокировку ресурса B
  3. Другой процесс пытается получить монопольную блокировку на ресурсе A и блокирует ожидание освобождения вашей общей блокировки на A.
  4. Вы пытаетесь взять общую блокировку на ресурсе B и заблокировать ожидание, пока другой процесс освободит свою эксклюзивную блокировку на B, за исключением того, что вы сейчас находитесь в тупиковой ситуации, которая определяется сервером и выбирает процесс убить.

N.B. В тупиках может быть больше игроков, чем просто 2. Иногда существует целая цепочка переплетенных действий, которые приводят к тупику, но принцип тот же.

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

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

1 голос
0 голосов
/ 11 мая 2009

У вас такое же поведение с adOpenForwardOnly?

Возможно, вы захотите проверить актуальность статистики SQL Server. Или вы можете заставить своего администратора баз данных перестроить все индексы. Многие проблемы с блокировкой связаны с устаревшей статистикой / индексами.

0 голосов
/ 11 мая 2009

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

В wikipedia

есть хорошее объяснение условий тупика.
0 голосов
/ 11 мая 2009

Чтения могут по-прежнему вызывать блокировки, чтобы БД могла гарантировать, что запись не выполняется в середине неатмического чтения. Другими словами, блокировка чтения гарантирует, что вы получите точный непротиворечивый снимок любых данных, которые вы выбираете.

0 голосов
/ 11 мая 2009

Это зависит от поведения обоих приложений. Ваше приложение, безусловно, может подождать, пока оно освободит ресурсы.

0 голосов
/ 11 мая 2009

Не было бы что-то подобное?

Другое приложение : запись в таблицу (получение блокировки записи на таблицу)

Ваше приложение : чтение из таблицы (получить блокировку чтения таблицы, невозможно из-за блокировки записи).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...