powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Борьба с блокировками через индексы...
16 сообщений из 16, страница 1 из 1
Борьба с блокировками через индексы...
    #39775829
Фотография SIMPLicity_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго дня!
Есть небольшая по размеру временная таблица TmpT , используется как промежуточная для вставки в "рабочую" WrkBigTable .
Наполняемость многократно варьируется - от 1 до 1000 строк. Несколько клиентов (через разные хранимки или напрямую) накидывают в TmpT свои рекордсеты, маркированные ключевым полем (KeyField). Клиентами запускается одна и та же хранимая процедура с соответствующим полю KeyField значением параметра - выбирает из TmpT записи, обрабатывает их и кидает в WrkBigTable .

Суть проблемы: для получения значения KeyField происходит выборка:
Код: sql
1.
begin transaction; select @NewKey = isnull(max(KeyField),0)+1 From TmpT WITH (UPDLOCK HOLDLOCK); insert into TmpT (KeyField , ...) values (@NewKey, ...); commit transaction

.
Вставка записей в TmpT, их выборка из TmpT и удаление,- совершенно ни как не связаны. В какой-то момент начинается конфликт. Причём, похоже, всё сходится именно на несчастной TmpT, а именно её KeyField .
По KeyField есть первичный ключ в связке ещё с одним полем. Почесав затылок и вспомним лекции Дмитрия Короткевича, не придумал ни чего лучшего, как создать отдельный некластерный индекс по KeyField. Индекс получился страшным (на 1000 обновлений всего 500 seek-ов), но сервер использует его в estimated plan для select @NewKey = isnull(max(KeyField),0)+1 From TmpT WITH (UPDLOCK HOLDLOCK) (!!!!)

Насколько удачным можно считать такое решение?

С одной стороны, индекс волочиться "мёртвым хвостом". С другой,- это, на мой взгляд, единственное решение в рамках неизменяемости архитектуры базы и приложения...

--------------------------
No ROM Basic...
Как-то так (на вскидку, не проверял ;-) ) :
Код: sql
1.
2.
3.
4.
5.
6.
7.
create table TmpT ( KeyField int not null
                            ,pointNumber int not null
                            ,otherField varchar(20)
                            ,anotherField int
                            );
Create primary key clustered TmpT_clust on  TmpT (KeyField asc, pointNumber asc );
create index TmpT_idx on  TmpT ( KeyField desc);


...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776062
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_,

Я бы это сделал через Service Broker для разделения отправителя и получателя. На стороне инициатора помещаете данные в очередь, а на стороне получателя забираете из очереди и обрабатываете. Используйте группы, чтобы из одной очереди могли забирать разные получатели или сформируйте несколько очередей. Кроме того, можно накопленные сообщения обрабатывать "оптом".
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776181
Фотография SIMPLicity_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владислав КолосовSIMPLicity_,

Я бы это сделал через Service Broker для разделения отправителя и получателя. На стороне инициатора помещаете данные в очередь, а на стороне получателя забираете из очереди и обрабатываете. Используйте группы, чтобы из одной очереди могли забирать разные получатели или сформируйте несколько очередей. Кроме того, можно накопленные сообщения обрабатывать "оптом".

Спасибо за комментарий, но этот вариант в данном случае неприемлем - слишком велико время прохождения всей цепочки.
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776281
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_,

еще один простой способ разделить читателей и писателей - превратить таблицу в InMemory.
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776392
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_Вставка записей в TmpT, их выборка из TmpT и удаление,- совершенно ни как не связаны. В какой-то момент начинается конфликт. Причём, похоже, всё сходится именно на несчастной TmpT, а именно её KeyField .Так конфликт происходит при получении новой KeyField? оно же редко вызывается, по сравнению с вставками в TmpT вообще, правильно?
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776406
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_,

Тип KeyField принципиален?
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776477
Фотография SIMPLicity_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmSIMPLicity_,

Тип KeyField принципиален?
Замена на uniqueidentifier?- не, "не катит" .... К тому же это не моя архитектура...
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776480
Фотография SIMPLicity_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexeyvgSIMPLicity_Вставка записей в TmpT, их выборка из TmpT и удаление,- совершенно ни как не связаны. В какой-то момент начинается конфликт. Причём, похоже, всё сходится именно на несчастной TmpT, а именно её KeyField .Так конфликт происходит при получении новой KeyField? оно же редко вызывается, по сравнению с вставками в TmpT вообще, правильно?

Конфликт происходит как в момент непосредственного захвата, так и в моменты других операций ... Ошибки спонтанные, плюс ко всему тут замешаны распределённые транзакции. И всё это происходит только на "боевой" базе. Сымитировать не удаётся :( ... Думаю переделать кластерный индекс в некластерный ;-) ....
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776499
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_Конфликт происходит как в момент непосредственного захвата, так и в моменты других операций ... Ошибки спонтанные, плюс ко всему тут замешаны распределённые транзакции. И всё это происходит только на "боевой" базе. Сымитировать не удаётся :(Ну, тут же может быть множество причин... Если даже точно неясно, где блокируется.

Можно, конечно, попробовать индекс, вдруг поможет.
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776575
tunknown
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_решение в рамках неизменяемости архитектуры базы и приложения...Насколько неизменяема структура? А бинарники пропатчить?

Что, если на TmpT повесить триггер на вставку, который будет сохранять этот isnull(max(KeyField),0)+1 в отдельную таблицу TmpTid из одного поля и из одной записи? Тогда блокировать будет нужно её и читать ключ из неё. TmpT будет на вставку доступна (почти)всегда.

Если вместо таблицы TmpTid генерить из триггера create/alter view TmpTid as select KeyField=123 с константой. Тогда блокировка будет связана со схемой, что позволит сместить проблему, но решит ли- неизвестно.
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776679
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_Замена на uniqueidentifier?- не, "не катит"Ну и ладно.
Что бы предложить чего-нибудь конструктивное, нужно понимать что вы называете "конфликтом".
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776681
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_,

Вам ничего не поможет, кроме технологических решений (Inmemory, переключение режима изоляции в вариант версионирования), потому, что запрос сканирует таблицу в поиске максимального значения. Накладывайте tablock, но это создаст узкое горло.
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776698
Фотография HandKot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_,
было подобное.
Заменил isnull(max(KeyField),0)+1 на поле identity
Но у Вас немного сложнее.
Как вариант (чисто теоритически), разделить таблицу на две
в одной KeyField как identity, в другой KeyField и значения рекордсетов
на первой написать insteadof тригер, в котором в первую заносятся одна строка с получение идентити и вставка данных рекордсетов во вторую
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776703
Dzianis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хорошо.
А если вынести нового значения KeyField на SEQUENCE?
или вариант от HandKot .
Индекс по KeyField оставить только для более быстрого поиска, что удалить/перенести
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776744
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmЧто бы предложить чего-нибудь конструктивное, нужно понимать что вы называете "конфликтом"+1
Дедлок, что ли?
...
Рейтинг: 0 / 0
Борьба с блокировками через индексы...
    #39776745
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HandKotКак вариант (чисто теоритически), разделить таблицу на две
в одной KeyField как identity, в другой KeyField и значения рекордсетовДа, тоже хотел такое предложить, но непонятно, что всё таки происходит, и в чём проблема, может, совсем в другом, не связанном с этой таблицей и с этим полем.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Борьба с блокировками через индексы...
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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