Две разные транзакции обновляют разные строки одной и той же таблицы одновременно

Среда: SQL SERVER 2008 R2, Windows.

СОЕДИНЕНИЕ-1: выполнение следующего

BEGIN TRANSACTION               

    UPDATE Check_lock with (rowlock)
    set LayoutType = 98
    where USERID between 1 and 7;

    WAITFOR DELAY '000:10:00';

COMMIT TRANSACTION;

СОЕДИНЕНИЕ-2: выполнение следующего

BEGIN TRANSACTION               

    UPDATE Check_lock with (rowlock)
    set LayoutType = 98
    where USERID between 15 and 20;

COMMIT TRANSACTION;

Постановка проблемы: я выполняю вышеуказанные транзакции через SQL Server Management Studio, создавая два соединения с одним и тем же сервером/базой данных на одном компьютере в одно и то же время. Хотя таблица одна и та же, и транзакции выполняются одновременно (не на 100% одновременно, потому что выполняются вручную), но обновляют разные строки (блокировка на уровне строк), тогда почему транзакция «Connection-2» не была немедленно зафиксирована и идет в подождите, пока первая транзакция не будет зафиксирована/завершена. ??

Пожалуйста, дайте мне знать, если я не ясно описал свой сценарий.


person Imran Amjad    schedule 09.07.2013    source источник
comment
Добро пожаловать в SO, вы должны добавить тег SQL к своему вопросу и не указывать свой адрес электронной почты в теле вопроса (вместо этого вы можете добавить его в свой профиль!)   -  person Awalias    schedule 09.07.2013
comment
Индексируется ли USERID? Используется ли индекс в плане выполнения? В противном случае сканирование для поиска строк, соответствующих USERID between 15 and 20, будет заблокировано в ожидании чтения строк, заблокированных исключительно первой транзакцией.   -  person Martin Smith    schedule 09.07.2013
comment
Почему вы ставите код WAITFOR DELAY '000:10:00';   -  person bgs    schedule 09.07.2013


Ответы (2)


Я думаю причина в этом:

«WITH (ROWLOCK) предоставляет оптимизатору подсказку запроса. Если SQL сочтет это возможным, он все равно может преобразовать блокировку строк в блокировку страницы или блокировку таблицы. Обычно это происходит только в том случае, если вы нажимаете очень большое количество строк. хотя - в основном он пытается уберечь вас от потребления дополнительных ресурсов с помощью множества блокировок строк».

Эта цитата была взята с этого форума MSDN: таблица-заблокирована, а-с-замком-строки-используется-в-операторе-обновления" rel="nofollow">http://social.msdn.microsoft.com/Forums/sqlserver/en-US/ 60238304-04e8-4f98-84d1-3ddf1ed786a9/почему-вся-таблица-заблокирована-пока-с-замком-замком-используется-в-операторе-обновления

Создание индекса для столбца USERID (как сказал Мартин Смит) может помочь, потому что оптимизатор SQL может использовать индекс и сделать вывод, что лучше блокировать строку, чем полное сканирование.

person miguelbgouveia    schedule 09.07.2013

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

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

person Bravo    schedule 05.03.2019