powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Направление сортировки кластерного индекса и Range Locks
3 сообщений из 3, страница 1 из 1
Направление сортировки кластерного индекса и Range Locks
    #39621684
aleksrov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет! В общем лазил по своим закладкам и нашел статью ,
"Например, если в базе есть Id 15 и Id 1025, и нет ни одного значения между ними, то при выполнении SELECT * FROM Users WHERE FacebookId = 500 будет наложена Shared блокировка на ключи с 15 до 1025", имеется ввиду при Serializable. Плюс мы тут с коллегой спорили про этот уровень, и главный вопрос был, а так ли это и влияет ли сортировка на блокировки?
Решил проверить

Код: 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.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
create table Test_Serial
( 
 id int not null, 
 txt varchar(10) null 
) 
go 

CREATE UNIQUE CLUSTERED INDEX [ClustIndex_Test_Serial] ON [dbo].[Test_Serial] ([id] asc) 
go 

insert into Test_Serial (id)  
values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10),  
(20), (21), (22), (23), (24), (25) 
go 

Begin tran Tran_one 
select id from dbo.Test_Serial with (holdlock) 
where id = 15 
--rollback tran Tran_one 

-- Выполняем в другом окне, обновление пройдет 
begin tran Tran_Two 
Update dbo.Test_Serial set txt = 'txt'  
where id = 10 
--rollback tran Tran_Two 

--Меняем where id = 20 и Select заблокирует этот update. 

go 
--Теперь делаем так. 
CREATE UNIQUE CLUSTERED INDEX [ClustIndex_Test_Serial] ON [dbo].[Test_Serial] 
([id] DESC) WITH (drop_existing = on) 
go 

--Теперь если повторить предыдущий select и update то ситуация будет обратная. 
--Update c where id = 20 проходит, а c where id = 10 нет.  

go 
--Теперь делаем так. Т.е. индекс не уникален. 
CREATE CLUSTERED INDEX [ClustIndex_Test_Serial] ON [dbo].[Test_Serial] 
([id] asc) WITH (DROP_EXISTING = ON) ON [PRIMARY] 
GO 

--При update ситуация такая же как и при уникальном индексе. 
-- А вот при insert нет. 

Begin tran Tran_one 
select id from dbo.Test_Serial with (holdlock) 
where id = 15 
--rollback tran Tran_one 

-- Это вставка не пройдет 
Begin tran Tran_two 
insert into dbo.Test_Serial 
values (20,'txt') 
--rollback tran Tran_two 
--И наоборот, если меняем 20 на 10, то вставка не проходит. 
--Т.е. здесь блокироуется диапазон с 10 до 19. 

--Если поменять направление сортировки у индекса то будет блокироваться диапазон с 11 до 20. 



По итогу.
Если индекс уникальный и когда мы выбираем id = 15 (когда в базе есть только 10 и 20), то при индексе ASC
Update where id = 10 - проходит
Update where id = 20 - нет
при индексе DESC
Update where id = 10 - нет
Update where id = 20 - проходит
Если индекс не уникален, то при update также, а вот insert нет, при индексе ASC
insert id = 10 - нет
insert id = 20 - да, т.е. идет блокировка с 10-19
при индексе Desc
insert id = 10 - да
insert id = 20 - нет, т.е. идет блокировка с 11-20
Обрыл весь гугл и не смог найти где бы это упоминалось. Если есть статьи, дайте ссылку.
Или может я не правильно делал опыт и поведение совсем не такое.
...
Рейтинг: 0 / 0
Направление сортировки кластерного индекса и Range Locks
    #39621706
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Направление сортировки кластерного индекса и Range Locks
    #39621893
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aleksrov,

Причем "next key" трактуется как физически, так и логически. Физичиский "next key" (который в порядке просмотра индекса) блокируется всегда.
Хорошо иллюстрируется примером:
Код: 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.
use tempdb;
go

create table Test (k int);
create index IX_Test on Test (k);

insert into Test (k)
values
 (1), (2), (3), (4);
go
 
select %%lockres%%, * from Test with (index = IX_Test);

-- case 1
begin tran;
set statistics xml on;
select * from Test with (serializable, index = IX_Test) where k between 2 and 3 order by k;
set statistics xml off;
exec sp_lock @@spid;
commit;

-- case 2
begin tran;
set statistics xml on;
select * from Test with (serializable, index = IX_Test) where k between 2 and 3 order by k desc;
set statistics xml off;
exec sp_lock @@spid;
commit;
go

drop table Test;
go


В case 1 физический "next key" совпадает с логическим.
В case 2 не совпадает. Как итог имеем ненужную блокировку на строку с k = 1.
...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Направление сортировки кластерного индекса и Range Locks
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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