Мертвая блокировка SQL Server 2005 года с некластеризованным индексом

Кто-либо может помочь мне для мертвой блокировки в SQL Server 2005?

Для простого теста у меня есть таблица "Book", которая имеет первичный ключ (идентификатор) и имя столбца. Индекс по умолчанию этого первичного ключа не кластеризируется.

Мертвая блокировка происходит когда две сессии, выполненные в то же время. Монитор действия показывает первую сессию "//, шаг 1" блокирует строку (избавленная блокировка) с X блокировками. Вторая сессия сохраняет строку U блокировкой и ключом U блокировка. Шоу изображения мертвой блокировки "//step2" первой сессии требуют ключа U блокировка.

Если индекс кластеризируется, в этом случае нет никакой мертвой блокировки. "//шаг 1" сохранит блокировку строки и блокировку ключа в то же время, таким образом, не будет никакой проблемы. Я могу понять, что блокировка строки также заблокирует индекс, так как вершина кластерного индекса является данными строки.

Но, почему некластеризованный индекс таким образом? Если вторая сессия удерживает клавишу U блокировка, почему "шаг 1" первой сессии не содержит эту блокировку, так как они - то же оператор обновления.

--// first session
BEGIN TRAN
  update Book set name = name where id = 1 //step 1
  WaitFor Delay '00:00:20'
  update Book set name = 'trans' where id = 1 //step2
COMMIT

--// second session
BEGIN TRAN
--// this statement will keep both RID(U lock) and KEY(U lock) if first session did not use HOLDLOCK
  update Book set name = name where id = 1
COMMIT
10
задан marc_s 20 January 2010 в 08:45
поделиться

3 ответа

Этот вопрос уже заставил меня поцарапать голову. Для меня это вопрос семантики. Мне кажется более естественным делать

<page size="a4">

, чем

<page>
  <size>a4</size>
</page>
-121--3095737-

W3C - События объектной модели документа - но как всегда... некоторые браузеры не поддерживают все.

-121--3397791-

Здесь релевантным фактором является использование столбца в предложении , где имеет некластеризованный индекс. Когда SQL Server обрабатывает обновление, это происходит примерно так:

  1. Поиск строк для обновления, установка U-блокировок для подключенных данных
  2. Обновление строк, установка X-блокировок для измененных данных

После завершения инструкции (при изоляции по умолчанию READ COMMITTED ) U-блокировки освобождаются, но X-блокировки удерживаются до тех пор, пока

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

  1. (Session 1, step 1) U блокировка значения ключа индекса для id = 1
  2. (Сеанс 1, шаг 1) Блокировка X в RID для строки с id = 1
  3. (Session 1, шаг 1) U блокировка снята
  4. (Session 2) U блокировка взята на значение ключа индекса для id = 1
  5. (Сеанс 2) Блокировка X заблокирована для RID для строки с id = 1
  6. (Session 1, step 2) U блокируется значение ключа индекса для id = 1 -- DEADLOCK

Однако, когда индекс является кластеризованным индексом, нет отдельного шага для преобразования ключа индекса в строку - значение кластеризованного индекса является идентификатором строки. Следовательно, блокировка заканчивается следующим образом:

  1. (сеанс 1, шаг 1) U блокировка значения ключа индекса для id = 1
  2. (Сеанс 1, шаг 1) U-блокировка обновлена до X-блокировки
  3. (Сеанс 2) Блокировка U заблокирована для значения ключа индекса для id = 1
  4. (Session 1, step 2) блокировка значения ключа индекса для id = 1
  5. (Сеанс 1, фиксация) блокировка освобождена
  6. (Сеанс 2) U блокировка предоставлена
  7. (Сеанс 2) U блокировка повышена до X блокировка
  8. (Сеанс 2) Блокировка разблокирована

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

11
ответ дан 4 December 2019 в 01:01
поделиться

Эта ссылка имеет много полезных предложений: неблокирует SQL Server между выбором / обновлением или несколькими выборами .

Вот некоторые очки, которые нужно рассмотреть, что может помочь людям ответить на ваш вопрос:

  1. Какая выделение транзакции вы используете?
  2. - это эскалация блокировки (например, из строки к странице), разрешена?
  3. Индекс на столбце «Имя»?
0
ответ дан 4 December 2019 в 01:01
поделиться

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

class HandlerFsm(object):

  _fsm = {
    ("state_a","event"): "next_state",
    #...
  }
-121--1117095-

Почти идентичен @ Thomas, но другой метод -

При условии, что dt1 больше dt2

if(dt1.Sutract(dt2).TotalMinutes < 5)
{
    // do
}

Основное отличие состоит в том, что он использует пространство памяти dt1 для выполнения вычитания.

Edit: использование коррекции TotalMinutes. Метод substract все еще присутствует в объекте datetime, поэтому я оставлю его здесь.

-121--2786173-

Ваше первое обновление ничего не изменяет:

update Book set name = name where id = 1

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

0
ответ дан 4 December 2019 в 01:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: