powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Заблокировать таблицу от удаления до конца транзакции
67 сообщений из 67, показаны все 3 страниц
Заблокировать таблицу от удаления до конца транзакции
    #39616123
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго времени суток!
Есть хранимка

Код: 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.
CREATE #tbGroup

MERGE tbGroup -- в 2 стороны: INSERT, DELETE
...

INSERT #tbGroup
FROM tbGRoup
WHERE ...

--пляски с использованием tbGroup.Id и не только

--сохраняем данные из кучи временных таблиц, у которых в том числе есть ссылки на tbGroup.Id, в постоянные
BEGIN TRAN
--ЗАБЛОКИРОВАТЬ tbGroup от удаления строк
DELETE tg -- + каскадное удаление из всех дочерних временных таблиц
    FROM #tbGroup tg 
    LEFT JOIN tbGroup g WITH(UPDLOCK) 
        ON g.Id = tg.Id
    WHERE g.Id IS NULL

MERGE 15 штук ...

DELETE 
FROM tbGroup tg 
WHERE ...

MERGE 15 штук ...

END TRAN



Поменять порядок в ней сейчас будет крайне тяжело.

Проблема в том, что эта хранимка может выполняться параллельно и к моменту объявления транзакции в tbGroup может уже не быть части строк, что были на момент заполнения #tbGroup - но они и не нужны. Я могу внутри транзакции каскадно удалить записи из #tbGroup и дочерних временных таблиц. Проблема в том, что и во время выполнения транзакции конкурентами могут быть удалены записи из tbGroup (вообще-то они тоже не нужны)

И тут 2 пути:
1. В каждой из 30 MERGE инструкций делать проверку на существование строки в tbGroup (и чет мне уже не кажется это решение не совсем правильным)
2. Заблокировать в начале транзакции tbGroup (желательно не всю, а только те строки, что есть в #tbGroup)
Как я себе это представляю - нарисовал выше. Вот правильно ли?

Про уровни изоляции и блокировки читал, но в реале использовал 1 раз. Так что не пинайте сильно.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616127
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, вставьте эксклюзивный апплок в начале процедуры сериализовав таким образом ее выполнение.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616131
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О чем вы, Сергей Алексеевич?
Да и не нужно мне блокировать таблицу в начале хранимки, нужно только в начале транзакции
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616137
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я так понимаю вы имели в виду sys.sp_getapplock чтобы реализовать синглтон.
Но это совсем не то, что мне нужно.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616165
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль ФаридовичЗаблокировать в начале транзакции tbGroup (желательно не всю, а только те строки, что есть в #tbGroup)
Как я себе это представляю - нарисовал выше. Вот правильно ли?Представляете правильно. Нарисовали не совсем правильно - желаемый результат не гарантирован.
Чтобы максимально приблизится к "желательно не всю, а только те строки, что есть в #tbGroup", у tblGroup должен быть индекс по Id и запрос написан так:
Код: sql
1.
2.
3.
4.
5.
6.
delete tg
from #tbGroup tg
where
 not exists(select 1 from tbGroup with (updlock, rowlock) where id = tg.id)
option
 (loop join);

Плюс в этом запросе придется обеспечить сканирование #tblGroup в порядке id, иначе можете получить дедлок.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616178
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm, спасибо за ответ
invmПлюс в этом запросе придется обеспечить сканирование #tblGroup в порядке id, иначе можете получить дедлок.
1. На #tbGroup есть кластерный PK по полю Id. Больше индексов нет. Этого будет достаточно?

2. #tbGroup может быть достаточно большой, и гонять tbGroup (сейчас 2M записей) вложенными циклами не самый лучший вариант.
В tbGroup есть проиндексированное поле OrgId.
Можно в этом случае инициировать блокировку не конкретных строк, а диапазона ключей, как-то так:
Код: sql
1.
2.
3.
select count(*) 
from tbGroup with (updlock, <подсказка для блокировки по диапазону ключей индекса>)
where OrgId = @OrgId


?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616794
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

авторво время выполнения транзакции конкурентами могут быть удалены записи из tbGroup

Ну и что?

Код: sql
1.
2.
3.
4.
5.
DELETE 
FROM tbGroup tg 
WHERE ...

MERGE 15 штук ...



это прекрасно переживёт.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616858
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владислав Колосов,
не переживет именно MERGE (во временнных таблицах будут ссылки на не существующие в tbGroup записи
invm дал ответ на мой первый вопрос.

Сейчас меня интересует
Код: sql
1.
<подсказка для блокировки по диапазону ключей индекса>)
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616870
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович
Код: sql
1.
<подсказка для блокировки по диапазону ключей индекса


holdlock
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616902
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Наколько я понял из статьи уровни гранулярности , блокировка по отдельным строкам и по диапазону ключей индекса - это одно и то же. Т.о. если я хочу заблокировать только те строки, что относятся к определенной организации, то я должен выполнить следующее:

Код: sql
1.
2.
3.
select count(*) 
from tbGroup with (INDEX(IX_tbGroup_Orgid), updlock, rowlock)
where OrgId = @OrgId


?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616919
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

и подумать о эскалации
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39616970
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридовичблокировка по отдельным строкам и по диапазону ключей индекса - это одно и то жеНе совсем. Но для вашей задачи можете так считать.

При ограничении OrgId = @OrgId можете написать вот так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
with tg as
(
 select top (cast(0x7fffffff as int)) id from #tbGroup order by id
)
delete tg
from
 tg left join
 tbGroup g with (updlock, index = IX_tbGroup_Orgid) on g.OrgId = @OrgId and g.id = tg.id;


В худшем случае (если не будет выбран NL для соединения таблиц) - получите блокировку всех строк в tbGroup для OrgId = @OrgId.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617007
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmВ худшем случае (если не будет выбран NL для соединения таблиц) - получите блокировку всех строк в tbGroup для OrgId = @OrgId
, а в лучшем, блокировку только тех, что есть в #tbGroup - красивое решение!
TaPaKи подумать о эскалации
Отсюда мне стало известно, что порог укрупнения блокировок по умолчанию равен 5000 строк. Т.о. для топ-50 моих организаций сервер будет пытаться автоматически укрупнить блокировку до уровня таблицы.

1. Можно ли увеличить этот порог для одной (можно и всех) таблиц в рамках одной транзакции скажем до 100 000?
(для меня важным моментом является возможность параллельной работы 2 пользователей из разных организаций)
2. При каком количестве строк (а наверное занимаемых ими страниц) лучше сразу указывать PAGELOCK вместо ROWLOCK?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617010
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

а где вы там "5000 строк" увидели ?
и да отключение эскалации там описано
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617013
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну и все эти ваши танцы, особенно с длинной транзакцией, в итоге приведут вас к дедлокам.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617036
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,
я увидел там 5000 блокировок.
Если у меня в таблице #tbGroup 5001 строка и стоит tbGroup with (rowlock),
разве это не вызовет попытку укрупнения блокировки до уровня таблицы?
TaPaKи да отключение эскалации там описано
Мне нужно не отключение, а перенастройка эскалации, причем желательно для одной таблицы в рамках одной транзакции.
Я так понимаю, увеличить порог укрупнения только для текущего соединения навряд ли получится, а тем более для одной таблицы

Поэтому видимо придется остановится на отключении эскалации:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
BEGIN TRY

 ALTER TABLE tbGroup SET LOCK_ESCALATION = DISABLE 
 BEGIN TRAN
 ...
 END TRAN 
 ALTER TABLE tbGroup SET LOCK_ESCALATION = AUTO

END TRY
BEGIN CATCH
 ...
 ALTER TABLE tbGroup (SET LOCK_ESCALATION = AUTO
END CACTH



Хотя по идее можно SET LOCK_ESCALATION = DISABLE засунуть внутрь транзакции.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617045
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль ФаридовичХотя по идее можно SET LOCK_ESCALATION = DISABLE засунуть внутрь транзакции.
Это заблокирует таблицу вообще до конца транзакции
Причем даже для селекта, и даже с nolock-м
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617053
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

У вас конкурентный доступ к ресурсу с несовместимыми блокировками. Откуда тут взяться эскалации?
Лучше уберите rowlock и позвольте серверу самому управлять гранулярностью блокировок.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617334
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

все равно не понял. Вас merge попытается из таблицы #tbGroup вернуть записи в tbGroup, которые были удалены другими процессами?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617339
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmШамиль Фаридович,

У вас конкурентный доступ к ресурсу с несовместимыми блокировками. Откуда тут взяться эскалации?
Лучше уберите rowlock и позвольте серверу самому управлять гранулярностью блокировок.

это здесь у него конкурентный доступ с несовместимыми блокировками?
Код: sql
1.
2.
3.
4.
5.
6.
delete tg
from #tbGroup tg
where
 not exists(select 1 from tbGroup with (updlock, rowlock) where id = tg.id)
option
 (loop join);
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617377
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKэто здесь у него конкурентный доступ с несовместимыми блокировками?Да.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617380
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmTaPaKэто здесь у него конкурентный доступ с несовместимыми блокировками?Да.
ну ок
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617418
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,

Вообще-то, при updlock любая конкурентная блокировка на таблице будет препятствовать эскалации.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617419
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmTaPaK,

Вообще-то, при updlock любая конкурентная блокировка на таблице будет препятствовать эскалации.
а откуда она возьмётся?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617436
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKа откуда она возьмётся?Мы рассматриваем работу в однопользовательском режиме?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617446
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmTaPaKа откуда она возьмётся?Мы рассматриваем работу в однопользовательском режиме?
нет, но ситуация кто первый встал у того и все тапки случится?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617469
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKinvmпропущено...
Мы рассматриваем работу в однопользовательском режиме?
нет, но ситуация кто первый встал у того и все тапки случится?
При параллельном запуске этого скрипта (даже с непересекающимися ID) эскалация будет невозможна из-за IU на таблице.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617473
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKно ситуация кто первый встал у того и все тапки случится?Это про эскалацию?
Случится, если на уровне таблице, на момент попытки эскалации, не будет ни одной чужой I*.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617475
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmЭто про эскалацию?
Случится, если на уровне таблице, на момент попытки эскалации, не будет ни одной чужой I*.
IS допустимы, они вполне с U "уживаются"
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617480
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
msLexTaPaKпропущено...

нет, но ситуация кто первый встал у того и все тапки случится?
При параллельном запуске этого скрипта (даже с непересекающимися ID) эскалация будет невозможна из-за IU на таблице.
это понятно, но у него немерянная транзакция с какими-то 15 мержами, и первая легко схватит всю таблицу и остальные дружно встанут
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617486
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKи первая легко схватит всю таблицу и остальные дружно встанут
если успеет, мы же говорим про параллельное выполнение.
к тому же, не каждый же поток будет добираться до 5000 заблокированных строк, так что "маленькие" порции будут намертво блокировать эскалацию
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617487
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKи первая легко схватит всю таблицуНа основании чего?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617491
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmTaPaKи первая легко схватит всю таблицуНа основании чего?
того что на момент удаления никто больше с ней не конкурирует
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617503
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
msLexIS допустимы, они вполне с U "уживаются"Только вот эскалация U будет до X, ибо U на таблицу не бывает.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617508
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKтого что на момент удаления никто больше с ней не конкурируетТ.е. таки рассматриваем вариант вообще без конкуренции, даже без читателей?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39617511
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmTaPaKтого что на момент удаления никто больше с ней не конкурируетТ.е. таки рассматриваем вариант вообще без конкуренции, даже без читателей?
ну отсюда не видно что же там
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618122
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго времени суток!
Подскажите пожалуйста, почему запись вида
Код: sql
1.
2.
3.
4.
5.
6.
DELETE tg 
FROM #tbGroup tg 
LEFT JOIN tbGroup g WITH(UPDLOCK, INDEX = IX_tbGroup_OrgId)
    ON  g.OrgId = @OrgId
	AND g.Id = tg.Id
WHERE g.Id IS NULL   


ил просто

Код: sql
1.
2.
SELECT COUNT(*) 
FROM tbGroup g WITH(UPDLOCK, INDEX = IX_tbGroup_OrgId) WHERE g.OrgId = @OrgId


делает кучу блокировок с TYPE = KEY (ровно столько, сколько групп в организации), причем блокируется именно индекс IX_tbGroup_OrgId,
вместо того, чтобы сделать 1 блокировку на диапазон.

Тем самым запрашиваемый диапазон действительно защищен от удаления и частично от обновления (от обновления поля OrgId),
но не защищен от добавления групп в ту же самую организацию (правда пока до конца неизвестно, нужно ли это вообще).

И все же интересно, как заставить сервер блокировать именно диапазон ключей индекса, в том числе и от вставки?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618130
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
зачем вам нужна блокировка на вставку в некий диапазон ключа?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618140
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль ФаридовичИ все же интересно, как заставить сервер блокировать именно диапазон ключей индекса, в том числе и от вставки?
21268301
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618146
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmmsLexIS допустимы, они вполне с U "уживаются"Только вот эскалация U будет до X, ибо U на таблицу не бывает.

Хмм, действительно.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618226
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
msLex,
спасибо, работает, sp_lock показывает, что сменился режим блокировки на RangeS-U, правда я вижу всю ту же кучу блокировок, вместо одной. Впрочем, у sp_lock в столбце type нет разделения между блокировкой по ключу и диапазону ключей.
Интересна еще одна вещь: на тестовых где в таблице tbGroup чуть больше 5000 строк, запрос вида
Код: sql
1.
2.
SELECT COUNT(*) 
FROM tbGroup g WITH(UPDLOCK, INDEX = IX_tbGroup_OrgId)


вызывает 5000 блокировок с уровнем гранулярности = KEY. Почему сервер не поднимает его до уровня таблицы, ну или хотя бы страниц?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618239
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

Каждая хранимая процедура создаст свой экземпляр #tbGroup.
От кого вы хотите заблокировать таблицу, от самого себя? :-)
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618242
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618245
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Совместимость блокировок (компонент Database Engine):
https://technet.microsoft.com/ru-ru/library/ms186396(v=sql.105).aspx
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618246
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль ФаридовичmsLex,
спасибо, работает, sp_lock показывает, что сменился режим блокировки на RangeS-U, правда я вижу всю ту же кучу блокировок, вместо одной. Впрочем, у sp_lock в столбце type нет разделения между блокировкой по ключу и диапазону ключей.
Интересна еще одна вещь: на тестовых где в таблице tbGroup чуть больше 5000 строк, запрос вида
Код: sql
1.
2.
SELECT COUNT(*) 
FROM tbGroup g WITH(UPDLOCK, INDEX = IX_tbGroup_OrgId)


вызывает 5000 блокировок с уровнем гранулярности = KEY. Почему сервер не поднимает его до уровня таблицы, ну или хотя бы страниц?
1. 5к блокировок это нечто вроде "по умолчанию", сервер расчитывает количество от нескольких параметров
2. до страниц эскалации не бывает
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618249
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блокировка диапазона ключей:
https://technet.microsoft.com/ru-ru/library/ms191272(v=sql.105).aspx

ЗЫ
это просто , чтобы народ мог посмотреть как в справочник, если вдруг нить рассуждений в текущем топике потерял
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618314
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридовичспасибо, работает, sp_lock показывает, что сменился режим блокировки на RangeS-U, правда я вижу всю ту же кучу блокировок, вместо одной
Это потому, что реальный ключ неуникального индекса IX_tbGroup_OrgId (OrgId, <clustered index key>) и Range блокировки накладываются именно на него.

Шамиль Фаридовичвызывает 5000 блокировок с уровнем гранулярности = KEY. Почему сервер не поднимает его до уровня таблицы, ну или хотя бы страниц?
До станицы, как вам уже сказали, сервер не эскаликует блокировки, только если сразу их выберет (можно ему помочь через paglock)
А до таблицы мешает любой активный селекет к данным из таблицы (если у вас не RCSI)
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39618356
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль ФаридовичИ все же интересно, как заставить сервер блокировать именно диапазон ключей индекса, в том числе и от вставки?Не бывает блокировки диапазона в таком виде, в каком вы его себе представляете - одна блокировка на произвольный диапазон ключей.
Блокировка диапазона в MSSQL - это блокировка (предыдущий ключ, ключ] и применяется исключительно для защиты от добавления строк в названный диапазон, чтобы обеспечить правильную работу на TIL serialiazable.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39625967
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем спасибо за ответы!
Задача немного усложнилась. Всю постановку передавать не буду, сконцентрируюсь на одной из подзадач:
необходимо в начале транзакции вставлять в таблицу
Код: sql
1.
2.
3.
4.
tbEventCalculationList 
(id int identity(1, 1), 
EventId int not null,
DataFormingDate datetime not null)



записи из таблицы #tbEventToGroup(EventId int, tbGroupId...)
и защитить до конца транзакции tbEventCalculationList от вставки конкурирующими транзакциями строк с EventId из #tbEventToGroup,
то есть мне нужно что-то вроде
Код: sql
1.
2.
3.
4.
    INSERT tbEventCalculationList WITH (UPDLOCK, HOLDLOCK, INDEX = IX_tbEventCalculationList _EventId)
    (EventId, DataFormingDate) 
    SELECT EventId, DataFormingDate
    FROM #tbEventToGroup


Проблема в том, что ругается на подсказку про индекс:
Код: sql
1.
Index hints are only allowed in a FROM or OPTION clause.


И я что-то не соображу, как засунуть хинт с индексом в предложение OPTION.
Или INSERT вообще не позволяет таких вещей, и я смогу диапазон ключей только после вставки и вызова подходящего предложения SELECT ?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39625973
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

по EventId уникальный индекс?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39625975
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
    INSERT tbEventCalculationList WITH (UPDLOCK, HOLDLOCK, INDEX = IX_tbEventCalculationList _EventId)
    (EventId, DataFormingDate) 
    SELECT EventId, DataFormingDate
    FROM #tbEventToGroup



это ошибка?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39625977
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_Oneэто ошибка? чукча не читатель?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39625984
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну и вообще

авторThe ability to specify the HOLDLOCK, SERIALIZABLE, READCOMMITTED, REPEATABLEREAD, or UPDLOCK hints on tables that are targets of INSERT statements will be removed in a future version of SQL Server. These hints do not affect the performance of INSERT statements. Avoid using them in new development work, and plan to modify applications that currently use them.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39625989
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKKonst_Oneэто ошибка? чукча не читатель?

я выделил пробел для ТС, если что. а вы читайте дальше
синтаксис неправильный (я только про это, дальше сами занимайтесь маразмом в рамках данной задачи)
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39625991
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_OneTaPaKпропущено...
чукча не читатель?

я выделил пробел для ТС, если что. а вы читайте дальше
синтаксис неправильный (я только про это, дальше сами занимайтесь маразмом в рамках данной задачи)
т.е. то что INDEX в хинет на insert вообще не опция(о чём и приведена ошибка), вас конечно не смущает
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626002
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKKonst_Oneпропущено...


я выделил пробел для ТС, если что. а вы читайте дальше
синтаксис неправильный (я только про это, дальше сами занимайтесь маразмом в рамках данной задачи)
т.е. то что INDEX в хинет на insert вообще не опция(о чём и приведена ошибка), вас конечно не смущает

так про это уже до меня сказали. или вы адвокат?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626005
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_Oneэто ошибка?
Это опечатка, без пробела тоже не работает.

Да, необходимо уточнить, что если в 2х параллельных транзакциях записи в таблицах #tbEventToGroup не пересекаются по EventId, то они не должны блокировать друг друга.

Konst_Oneпо EventId уникальный индекс?
Нет, уникальный индекс только по tbEventCalculationList.Id
Вообще эта таблица в разработке, и я могу повесить на EventId кластерный индекс, если это поможет решить задачу.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626010
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

Кластерный индекс не делает поле уникальным. Если нет уникальности значения, то надо что бы все сесии знали что же за значения вы вставляете. А вообще бред какой-то, если первая сессия вставляет EventId1 и EventId2, вторая сессия встав EventId3, EventId1 втроую выбрасываем и теряем EventId3?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626018
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK если первая сессия вставляет EventId1 и EventId2, вторая сессия встав EventId3, EventId1 втроую выбрасываем и теряем EventId3?
Почему выбрасываем?
вторая сессия просто ждет, пока закончится первая.
В то же самое время 3ья сессия с EventId4, EventId5 должна спокойно параллельно выполняться.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626021
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

авторвторая сессия просто ждет, пока закончится первая.зачем? в чём перформанс то?
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626026
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя честно говоря, со второй сессией все так просто.
В #tbEventToGroup не зря есть поле DataFormingDate.
Если на момент получения блокировки окажется,
что в tbEventCalculationList самая последняя запись с EventId1 имеет DataFormingDate >= #tbEventToGroup.DataFormingDate, то строка с EventId1 будет удалена из #tbEventToGroup и данные по EventId1 во второй сессии сохраняться не будут.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626028
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKШамиль Фаридович,

авторвторая сессия просто ждет, пока закончится первая.зачем? в чём перформанс то?
Тут дело не производительности, а в целостности данных.
Если разрешить конкурентам параллельно сохранять данные по одним и тем же EventId, то они моментально ее порушат.
А еще могут потереть свежие данные старыми.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626033
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль ФаридовичTaPaKШамиль Фаридович,

пропущено...
зачем? в чём перформанс то?
Тут дело не производительности, а в целостности данных.
Если разрешить конкурентам параллельно сохранять данные по одним и тем же EventId, то они моментально ее порушат.
А еще могут потереть свежие данные старыми.
у вас какая-то странная/не правильная/отвратительная архитектура. Запретите параллельную вставку и не мучайте народ реализацией костыля
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626050
Шамиль Фаридович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,
стадия 1. Отрицание (или запрет).

Даже не буду обсуждать требования заказчика.

Лучше вернемся к сабжу, расширю постановку.
Есть некая процедура по расчету стоимостей/группировке ивентов (примерный макет в первом сообщении - важно отметить, что в ней есть 2 больших блока - расчет данных во временных таблицах и их сохранение, обернутое в транзакцию).
Ивент туда может передаться как 1, так и пол таблицы tbEvent (в ней сейчас 6M записей).
Естественно, что те вызовы, в которые передали меньшее количество ивентов будут отрабатывать быстрее.
Более того, маленькие вызовы чаще всего обладают более актуальными данными, и большой вызов, когда наконец допрется до начала транзакции, не должен перетирать пересчитанные за время его выполнения ивенты своими потерявшими актуальность данными.

Для этого я хочу сделать таблицу tbEventCalculationList, в которую каждая транзакция будет класть список пересчитанных ей ивентов.
И в начале транзакции пытаться вставить в эту таблицу ивенты из #tbEventToGroup за исключением тех, что потеряли актуальность и защитить этот диапазон от конкурентов. Пока я не придумал, как это реализовать.

Есть альтернативный вариант Б: таблица tbEventCalculationState, куда скопируются все строки из tbEvent(и будут далее синхронизироваться), а каждая процедура по расчету будет просто менять DataFormingDate у соответствующих ивентов.
Здесь вроде все просто, вешаешь holdlock и никто твои ивенты до конца транзакции не пересчитает.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626063
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль ФаридовичБолее того, маленькие вызовы чаще всего обладают более актуальными данными, и большой вызов, когда наконец допрется до начала транзакции, не должен перетирать пересчитанные за время его выполнения ивенты своими потерявшими актуальность данными.Читайте про уровень изоляции SNAPSHOT и как там реализована защита от подобных случаев.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626065
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

А почему последовательно не хотите обрабатывать? Отправляйте все запросы в сервис брокер и выбирайте из очереди по одному. Если уж транзакции не устраивают.
...
Рейтинг: 0 / 0
Заблокировать таблицу от удаления до конца транзакции
    #39626077
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шамиль Фаридович,

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


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