powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / lock
5 сообщений из 5, страница 1 из 1
lock
    #39886960
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Никак не могу понять как в скл сервере работают блокировки. Допустим есть таблица T с 3 полями INT A, B, C. Без индексов.
И там 4 записи, у двух например в поле А значение 1. Уровень транзакций - READ COMMITTED.
Что происходит при выполнении запроса:
Код: sql
1.
UPDATE T set B = 1 WHERE A = 1


?
Допустим каждая запись это ROW. Начинается TABLE SCAN.
1.Попытка установить блокировку U на ROW1. Если успешно идем дальше, нет - ждем.
2.Аналогично для ROW2
3.Аналогично для ROW3
4.Аналогично для ROW4

То есть в какой то момент на всех записях стоит U? Либо на каждом шаге проверяется условие и только тогда ставится U?
В какой момент она заменятся на Х? перед самым коммитом?

Собственно если параллельно выполнить запрос
Код: sql
1.
SELECT * FROM T WHERE C = 10


То при условии что записи будут блокироваться в разном порядке возможен дедлок? Селект наткнулся на ROW на котором апдейт уже оставил U, в то же время апдейт не сможет сделать из U->X тк на записи стоит S от селекта?
...
Рейтинг: 0 / 0
lock
    #39886968
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892
Либо на каждом шаге проверяется условие и только тогда ставится U?
В какой момент она заменятся на Х? перед самым коммитом?
Все не так.

В вашем конкретном случае сканирования кучи, упрощенно:
- на строку ставится U
- если строка удовлетворяет предикату, U конвертируется в X и значение столбца обновляется, иначе U снимается.

И так для каждой сканируемой строки.
...
Рейтинг: 0 / 0
lock
    #39886987
Gerros
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892
Собственно если параллельно выполнить запрос
Код: sql
1.
SELECT * FROM T WHERE C = 10

То при условии что записи будут блокироваться в разном порядке возможен дедлок? Селект наткнулся на ROW на котором апдейт уже оставил U, в то же время апдейт не сможет сделать из U->X т.к. на записи стоит S от селекта?
Deadlock не случится. Update будет ждать, select прочитает запись и снимет S-lock (если в read committed), update сменит U-lock на X-lock, обновит строку, снимет блокировку и пойдёт дальше. Теперь обратный вариант: select хочет поставить S-lock на следующую строку, но на ней X-lock от update, поэтому select ждёт снятия. Когда update закончит, он снимет X-lock и select продолжит работу. Это упрощённо, без IS и IX блокировок.
Если select в serializable, а update по-прежнему в read committed, deadlock тоже не случается: select не снимает наложенный S-lock до завершения транзакции, но update снимает X-lock после каждого изменения. Что бы ни делал update, select рано или поздно прочитает всё что ему нужно и снимет свой S-lock, после чего update сможет продолжить и завершить свою работу.

Deadlock-и возникают, когда оба конкурирующих процесса в repeatable read и выше.
...
Рейтинг: 0 / 0
lock
    #39886991
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892,

добавлю к ответившим:
что бы лучше понять механизм блокировок запустите на тестовых вариациях запросов трассироку/xevent на события lock:aquired/lock:released.
тогда вы будете видеть наглядную картину что происходит в момент наложения/снятия блокировок
...
Рейтинг: 0 / 0
lock
    #39887035
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892,

Дополню.

Дедлочность select- update (в смысле читатель - писатель) зависит от множества факторов: наличия индексов, TIL читателя, хинтов в запросе, порядка просмотра записей.
Утверждение
Gerros
Deadlock-и возникают, когда оба конкурирующих процесса в repeatable read и выше.
неверное.
Дедлочить может и когда читатель на read committed. Для писателя же TIL практически не важен.
В вашем конкретном случае (таблица-куча без индексов) дедлока не будет, потому что читатель не накладывает более одной блокировки при обработке строки и не удерживает ее до конца транзакции.

Изучать процессы блокирования с помощью Extended Events, ИМХО, слишком накладно.
Гораздо проще в SSMS вот так (само-собой в тестовом окружении):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
use tempdb;
go

create table dbo.t (id int, a int);
insert into dbo.t values (1, 0), (1, 2), (2, 3);
create index IX_t__id on dbo.t (id);
go

/*Какие ресурсы будут блокироваться*/
select object_id('dbo.t');
select %%lockres%%, * from dbo.t;
select %%lockres%%, * from dbo.t with (index = IX_t__id);
go

print '------------------------------------------ Table Scan -------------------------------------------------------';
begin tran;
dbcc traceon(3604, 1200, -1) with no_infomsgs;
update t set a = 100 from dbo.t t with (index = 0) where id = 1 and a > 0;
dbcc traceoff(3604, 1200, -1) with no_infomsgs;
rollback;
print '-------------------------------------------------------------------------------------------------------------';

print '------------------------------------------ Index Seek -------------------------------------------------------';
begin tran;
dbcc traceon(3604, 1200, -1) with no_infomsgs;;
update t set a = 100 from dbo.t t with (index = IX_t__id) where id = 1 and a > 0;
dbcc traceoff(3604, 1200, -1) with no_infomsgs;
rollback;
print '-------------------------------------------------------------------------------------------------------------';
go

drop table dbo.t;
go


Результаты будут на вкладке messages
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / lock
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]