Тупики - это действительно поможет? - PullRequest
6 голосов
/ 30 июля 2010

Итак, у меня есть запрос, который постоянно блокирует меня. Люди, которые хорошо знают систему, не могут понять, почему sproc блокируется, но они говорят мне, что я должен просто добавить это к этому:

SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Это действительно правильное решение? Что это делает?

Ответы [ 5 ]

6 голосов
/ 30 июля 2010
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Это приведет к тому, что система будет возвращать несоответствующие данные, включая дубликаты записей и пропущенные записи. Подробнее на Ранее пропущенные строки могут быть пропущены, если используется подсказка NOLOCK или здесь на Бомба замедленного действия - проблема согласованности с NOLOCK / READ UNCOMMITTED .

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

Если вам нужна карта выхода из тюрьмы, включите изоляция моментального снимка :

ALTER DATABASE MyDatabase
SET READ_COMMITTED_SNAPSHOT ON

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

5 голосов
/ 30 июля 2010

NOCOUNT не даст вашему запросу вернуть количество строк обратно в вызывающее приложение (т. Е. Затронуто 1000000 строк).

REAC UNCOMMITTED уровня изоляции транзакций позволит выполнять грязное чтение, как указано здесь .

Уровень изоляции может помочь, но вы хотите разрешить грязное чтение?

3 голосов
/ 30 июля 2010

Случайное добавление SET параметров к запросу вряд ли поможет, боюсь

SET NOCOUNT ON

Не повлияет на проблему.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

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

Решение проблемы взаимоблокировки зависит от типа тупика. Это не будет иметь никакого эффекта, если проблема заключается в взаимоблокировке 2 писателей из-за нелинейного упорядочения запросов на блокировку. (транзакция 1 обновляет строку a, транзакция 2 обновляет строку b, затем tran 1 запрашивает блокировку на b и tran 2 запрашивает блокировку на a)

Можете ли вы опубликовать оскорбительный запрос и график тупиков? (если вы используете SQL 2005 или более позднюю версию)

2 голосов
/ 30 июля 2010

Лучшее руководство:

http://technet.microsoft.com/es-es/library/ms173763.aspx

Фрагмент:

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

Транзакции, выполняющиеся на уровне READ UNCOMMITTED, не создают общих блокировок, чтобы другие транзакции не могли изменять данные, считываемые текущей транзакцией.Транзакции READ UNCOMMITTED также не блокируются исключительными блокировками, которые не позволяют текущей транзакции читать строки, которые были изменены, но не зафиксированы другими транзакциями.Когда эта опция установлена, возможно чтение незафиксированных изменений, которые называются грязными чтениями.Значения в данных могут быть изменены, и строки могут появляться или исчезать в наборе данных до конца транзакции.Этот параметр имеет тот же эффект, что и установка NOLOCK для всех таблиц во всех инструкциях SELECT в транзакции.Это наименее ограничивающий уровень изоляции.

В SQL Server вы также можете минимизировать конкуренцию за блокировку, защищая транзакции от грязного чтения незафиксированных изменений данных, используя:

Уровень изоляции READ COMMITTEDс параметром базы данных READ_COMMITTED_SNAPSHOT, установленным в ON.Уровень изоляции SNAPSHOT

.

0 голосов
/ 01 августа 2010

С другой стороны, есть два других аспекта, которые могут помочь.

1) Индексы и индексы, используемые SQL. Стратегия индексирования, используемая в таблицах, будет влиять на количество строк. Если вы вносите изменения в данные с использованием уникального индекса, вы можете уменьшить вероятность взаимных блокировок.

Один алгоритм - конечно, он не будет работать во всех случаях. Использование NOLOCK является целевым, а не глобальным.

The "old" way:
UPDATE dbo.change_table
   SET somecol = newval
 WHERE non_unique_value = 'something'

The "new" way:
INSERT INTO #temp_table
    SELECT uid FROM dbo.change_table WITH (NOLOCK)
     WHERE non_unique_value = 'something'

UPDATE dbo.change_table
   SET somecol = newval
  FROM dbo.change_table c
       INNER JOIN
       #temp_table t
       ON (c.uid = t.uid)

2) Продолжительность транзакции Чем дольше транзакция открыта, тем больше вероятность возникновения конфликта. Если есть способ сократить время, в течение которого записи остаются заблокированными, вы можете уменьшить вероятность возникновения тупиковой ситуации. Например, выполните столько операторов SELECT (например, поисков) в начале кода, а не выполняйте INSERT или UPDATE, затем выполняйте поиск, затем INSERT и затем другой поиск. Здесь можно использовать подсказку NOLOCK для SELECT в «статических» таблицах, которые не изменяются, уменьшая «след» блокировки кода.

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