2015-04-07 4 views
0

У меня есть сервер MS SQL с базой данных, содержащей несколько таблиц. Каждая таблица имеет поле «SN». Несколько клиентов могут работать с этой базой данных, но каждый клиент работает только с записями со своим значением SN.Как настроить сервер MS SQL, чтобы избежать блокировки обновления (LCK_M_U)

Один тип клиентского приложения - это устаревшее программное обеспечение, написанное на python с использованием pyobbc. Насколько я понимаю, это программное обеспечение может создавать длинные транзакции - он может выполнять инструкции UPDATE или INSERT и передавать их всего несколько часов спустя. Я знаю, что это неправильно делать, но не желательно изменять это программное обеспечение.

Уровень изоляции транзакции установлен на READ_COMMITED с параметром READ_COMMITTED_SNAPSHOT, установленным в положение ON.

Все работает нормально, за исключением следующего сценария:

  1. Во-первых, наследие клент начинает транзакцию, которая обновляет записи ти его SN значение, скажем приложение SN = 1
  2. Другой клиент пытается обновить записи с его SN значение , скажем, SN = 2

Эта ситуация приводит к LCK_M_U блокировки для второго клиента: ridlock поле = 1 PageId = 311 DBID = 5 ид = lock2776cf380 режим = X associatedObjectId = ... много чисел здесь ...

Хотя эти два клиента используют разные значения SN, это приводит к блокировке. Я подозреваю, что это происходит из-за того, что SQL SQL блокирует не определенные строки, а страницу (набор строк, я думаю).

В соответствии с вопросом SO (Is it possible to force row level locking in SQL Server?) блокировка ряда не гарантируется из-за эскалации блокировки.

Я считал установку уровня изоляции транзакций «READ UNCOMMITTED», но я не уверен, что это правильный путь.

Есть ли способ правильно настроить сервер MS SQL для разрешения этой блокировки и разрешить «одновременное» обновление разных строк?

+0

Вы можете разделить таблицы на основе SN. это устранит конфликты блокировки между несколькими клиентами. – ughai

+0

Не уверен, что это хорошо. Большинство таблиц содержат только одну запись с конкретным SN (она может быть уникальной по всей таблице, как первичный ключ), и может быть большое количество различных SN. Также в соответствии с https://msdn.microsoft.com/en-us/library/ms190787.aspx существуют ограничения на количество разделов. – Roman

ответ

0

Я нашел решение, которое, кажется, работает нормально для меня. Он описан в this topic on microsoft forum. Идея состоит в том, чтобы создавать индексы для поля SN в таблицах следующим образом:

CREATE INDEX IX_SN ON TABLE_NAME(SN) 
0

Разбивка на SN может быть лучшим способом. Существует еще один метод, который вы можете использовать, но используйте его с осторожностью. Вы можете отключить эскалацию блокировки, включив флаг трассировки 1211. Однако этот флаг трассировки отключает всю эскалацию блокировки в глобальном масштабе в экземпляре SQL Server. Эскалация блокировки служит очень полезной цели в SQL Server, максимизируя эффективность запросов, которые в противном случае замедляются накладными расходами на приобретение и освобождение нескольких тысяч блокировок. Эскалация блокировки также помогает свести к минимуму требуемую память для отслеживания блокировок. Память, которую SQL Server может динамически распределять для структур блокировок, является конечной, поэтому, если вы отключите эскалацию блокировки и память блокировки становится достаточно большой, попытки выделить дополнительные блокировки для любого запроса могут завершиться неудачно.

+0

Спасибо за ваше предложение. Что касается раздела - см. Мой первый комментарий ниже оригинального вопроса.Отключение блокировки блокировки - это не путь, потому что экземпляр сервера также обслуживает другие базы данных, и такое изменение может быть нежелательным. – Roman

Смежные вопросы