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

Есть такая задача, обеспечить параллельную выборку данных двумя (или более) пользователями, чтобы они не выбрали одни и те же записи для обработки.

Пользователь 1 выбирает студентов из школ 1,2 и 3. Пользователь 2 пытается выбрать студентов из школ 3,4 и 5. Поскольку пользователь 1 начал первым, он должен получить список студентов из школ 1, 2 и 3 и пометить их для обработки. Пользователь 2 должен получить студентов только из школ 4 и 5. При этом надо использовать минимально необходимый уровень изоляции. Понятно, что можно залочить всю таблицу и добиться результата, но это не приемлемо.

Я думаю сделать так:
1. Установить уровень изоляции repeatable read
2. Открыть транзакцию
3. Сохранить студентов из школ 1, 2 и 3 в таблицу-переменную
4. В той же транзакции проапдейтить записи студентов со статусом 'S' (чтобы другой пользователь эти записи не трогал)
5. Закомиттить транзакцию.

В это время второй пользователь попытается запустить тот-же код для школ 3,4 и 5. Он не сможет залочить нужные записи и его сессия будет ждать окончания транзакции первого пользователя. Когда первый пользователь закончит свою транзакцию, то студенты школы 3 уже будет помечены статусом 'S' и второй пользователь их не получит.

Подскажите, я мыслю в правильном направлении?

Примерный код ниже.

Спасибо.


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
DECLARE @json varchar(max) =
N'{
"schoolIds": [1, 2, 3]
}'

DECLARE @studentList TABLE (id bigint)

set transaction isolation level repeatable read
begin tran 
insert into @studentList(id)
select stg_id from stg_student stg 
join openjson(@json,'$.schoolIds') sc on stg.schoolId=value  and ISNULL(status,'') <> 'S' 

update [dbo].[stg_student] set status = 'S' 
from [dbo].[stg_student] s
join @studentList sl
on s.stg_id = sl.id

commit tran
set transaction isolation level read committed
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880263
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roust_m,

как минимум, эти два запроса
Roust_m
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
insert into @studentList(id)
select stg_id from stg_student stg 
join openjson(@json,'$.schoolIds') sc on stg.schoolId=value  and ISNULL(status,'') <> 'S' 

update [dbo].[stg_student] set status = 'S' 
from [dbo].[stg_student] s
join @studentList sl
on s.stg_id = sl.id


можно объединить в один
Код: sql
1.
2.
3.
4.
5.
update stg 
set stg.status = 'S' 
output inserted.stg_id into @studentList(id)
from stg_student stg 
join openjson(@json,'$.schoolIds') sc on stg.schoolId=value  and ISNULL(status,'') <> 'S'
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880272
Фотография Roust_m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

Хорошо, а как по поводу уровня изоляции? Он достаточный для получения нужного результата? Также не является ли он избыточным?
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880281
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roust_m,

авторЕсть такая задача, обеспечить параллельную выборку данных двумя (или более) пользователями, чтобы они не выбрали одни и те же записи для обработки.


readpast
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880296
Фотография Roust_m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKRoust_m,

авторЕсть такая задача, обеспечить параллельную выборку данных двумя (или более) пользователями, чтобы они не выбрали одни и те же записи для обработки.


readpast

Как-то не очень надежно. А вдруг там записи залочены по другой причине (другой операции) и ни один из пользователей их не получит.
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880300
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roust_mTaPaKRoust_m,

пропущено...


readpast

Как-то не очень надежно. А вдруг там записи залочены по другой причине (другой операции) и ни один из пользователей их не получит.
repeatable read не обеспечивает праллельную обработку
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880312
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roust_m,

Как быть, если один хочет (1, 2, 3), а другой, например, (2, 3)?
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880315
L_argo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пусть юзеры вызывают ХП.
А ХП заносит сделанный выбор в табличку. Другой юзер тоже заносит свой выбор, но только то, чего еще там нет.
Потом селектит только свое вставленное.

Логику можно сделать более сложной.
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880319
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roust_m,

В общем, вот вам "рыба", дальше допилите под свои требования:
Код: 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.
begin tran 
insert into @studentList(id)
select stg_id from stg_student stg 
join openjson(@json,'$.schoolIds') sc on stg.schoolId=value  and ISNULL(status,'') <> 'S' 

declare @res nvarchar(255), @result int

declare res cursor local fast_forward for
 select N'school' + cast(id as nvarchar(10)) from @studentList

open res
while 1 = 1
 begin
  fetch next from res into @res
  if @@fetch_status <> 0
   break;

  exec @result = sp_getapplock @res, N'Exclusive', N'Transaction', -1
  if @result <> 0 -- ошибка
   begin
    ...
   end
 end
close res
deallocate res

update [dbo].[stg_student] set status = 'S' 
from [dbo].[stg_student] s
join @studentList sl
on s.stg_id = sl.id

commit tran
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880320
Ftt330
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Roust_mЕсть такая задача, обеспечить параллельную выборку данных двумя (или более) пользователями, чтобы они не выбрали одни и те же записи для обработки.

Очередь.
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880733
Фотография Roust_m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmRoust_m,

Как быть, если один хочет (1, 2, 3), а другой, например, (2, 3)?

Если тот, кто хочет 1,2,3 пришел первым, то второй ничего не получает и должен выбрать что-то другое.
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880734
Фотография Roust_m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
L_argoПусть юзеры вызывают ХП.
А ХП заносит сделанный выбор в табличку. Другой юзер тоже заносит свой выбор, но только то, чего еще там нет.
Потом селектит только свое вставленное.

Логику можно сделать более сложной.

Примерно тоже самое я и пытаюсь сделать. Юзеры заносят выборку в свою таблицу и в общей таблице помечают то что они выбрали, чтобы другие это же не взяли. Просто надо разрулить ситуацию когда они почти одновременно обращаются за выборкой.
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880735
Фотография Roust_m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ftt330Roust_mЕсть такая задача, обеспечить параллельную выборку данных двумя (или более) пользователями, чтобы они не выбрали одни и те же записи для обработки.

Очередь.

Не совсем понятно. В какой форме?
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880738
Фотография Roust_m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmRoust_m,

В общем, вот вам "рыба", дальше допилите под свои требования:
Код: 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.
begin tran 
insert into @studentList(id)
select stg_id from stg_student stg 
join openjson(@json,'$.schoolIds') sc on stg.schoolId=value  and ISNULL(status,'') <> 'S' 

declare @res nvarchar(255), @result int

declare res cursor local fast_forward for
 select N'school' + cast(id as nvarchar(10)) from @studentList

open res
while 1 = 1
 begin
  fetch next from res into @res
  if @@fetch_status <> 0
   break;

  exec @result = sp_getapplock @res, N'Exclusive', N'Transaction', -1
  if @result <> 0 -- ошибка
   begin
    ...
   end
 end
close res
deallocate res

update [dbo].[stg_student] set status = 'S' 
from [dbo].[stg_student] s
join @studentList sl
on s.stg_id = sl.id

commit tran



Я не совсем понимаю как это работает. Залочить надо таблицу stg_student (желательно не всю, а минимально необходимые записи), после чего выбрать из нее нужные записи и пометить их как выбранные, чтобы следующий пользователь не взял себе те же самые записи.
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880758
L_argo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Просто надо разрулить ситуацию когда они почти одновременно обращаются за выборкой. Если это будет делать одна ХП, то коллизий не будет.
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880762
Фотография Roust_m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
L_argoПросто надо разрулить ситуацию когда они почти одновременно обращаются за выборкой. Если это будет делать одна ХП, то коллизий не будет.

Это будет реализовано в одной хранимой процедуре, но запускаться она будет многими пользователями. Почему не будет коллизий?
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880777
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roust_mЗалочить надо таблицу stg_studentТаблицу надо не лочить, а сериализовать к ней доступ по определенным критериям. Что данный код и делает на основе пользовательских блокировок.

Если есть справочник школ, то можно еще и так
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
begin tran 
insert into @studentList(id)
select stg_id from stg_student stg 
join openjson(@json,'$.schoolIds') sc on stg.schoolId=value  and ISNULL(status,'') <> 'S' 

declare @c int;
select
 @c = count(*)
from
 @studentList a join
 [Справочник школ] with (rowlock, updlock) b on b.id = a.id;

update [dbo].[stg_student] set status = 'S' 
from [dbo].[stg_student] s
join @studentList sl
on s.stg_id = sl.id

commit tran
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880778
L_argo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roust_mЭто будет реализовано в одной хранимой процедуре, но запускаться она будет многими пользователями. Почему не будет коллизий?Потому что эта процедура сначала вставляет только свое и потом читает только свое.

Шутки ради можно индекс уникальный поставить, чтобы вставить одну и ту же ID два раза было в принципе нельзя. :)
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880781
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
L_argoRoust_mЭто будет реализовано в одной хранимой процедуре, но запускаться она будет многими пользователями. Почему не будет коллизий?Потому что эта процедура сначала вставляет только свое и потом читает только свое.

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

вот Вам демо пример реализации.

создаёте сессию 1, копируете пример:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
-- тестовая таблица
create table tempdb.dbo.t1 (id int, val int default 0);
insert tempdb.dbo.t1 (id) values (1),(2),(3),(4),(5);

begin tran
select * from tempdb.dbo.t1 with (readpast); -- первый пользователь выбирает все доступные строки для принятия решения на редактирование
select * from tempdb.dbo.t1 with (updlock,readpast) where id in (1,3); -- забрать строки для редактирования
update tempdb.dbo.t1 with (readpast) set val = 2 where id in (1,3); -- обновить указанные строки

select * from tempdb.dbo.t1 with (readuncommitted);

-- Выполнить до этой строки, выполнить пакет второй сессии, просмотреть результаты, затем выполнить строки ниже.

rollback
drop table tempdb.dbo.t1



создаёте сессию 2, имитирующую. работу второго пользователя, та же последовательность запросов, что и для первого:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
begin tran
select * from tempdb.dbo.t1 with (readpast); -- второй пользователь выбирает всё, что не выбрал первый для принятия решения на редактирование
select * from tempdb.dbo.t1 with (updlock,readpast) where id in (2,4); -- забрать строки для редактирования
update tempdb.dbo.t1 with (readpast) set val = 2 where id in (2,4); -- обновить указанные строки

select * from tempdb.dbo.t1 with (readuncommitted); -- просмотреть всю таблицу

rollback
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39880857
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В первом запросе для наглядности лучше указать set val = 1.
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39881297
Фотография Roust_m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владислав Колосов,

Спасибо, попробую
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39881397
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roust_mПользователь 1 выбирает студентов из школ 1,2 и 3. Пользователь 2 пытается выбрать студентов из школ 3,4 и 5. Поскольку пользователь 1 начал первым, он должен получить список студентов из школ 1, 2 и 3 и пометить их для обработки. Пользователь 2 должен получить студентов только из школ 4 и 5. При этом надо использовать минимально необходимый уровень изоляции. Понятно, что можно залочить всю таблицу и добиться результата, но это не приемлемо.Каюсь, невнимательно прочитал задачу.
Если есть справочник школ, решается так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
begin tran

insert into @studentList(id)
select
 stg_id
from
 openjson(@json,'$.schoolIds') scl join
 [Справочник школ] sc with (updlock, readpast) on sc.schoolId = a.value join
 stg_student stg on stg.schoolId = sc.schoolId and ISNULL(stg.status,'') <> 'S' 

update [dbo].[stg_student] set status = 'S' 
from [dbo].[stg_student] s
join @studentList sl
on s.stg_id = sl.id

commit tran
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39882201
Фотография Roust_m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmRoust_mПользователь 1 выбирает студентов из школ 1,2 и 3. Пользователь 2 пытается выбрать студентов из школ 3,4 и 5. Поскольку пользователь 1 начал первым, он должен получить список студентов из школ 1, 2 и 3 и пометить их для обработки. Пользователь 2 должен получить студентов только из школ 4 и 5. При этом надо использовать минимально необходимый уровень изоляции. Понятно, что можно залочить всю таблицу и добиться результата, но это не приемлемо.Каюсь, невнимательно прочитал задачу.
Если есть справочник школ, решается так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
begin tran

insert into @studentList(id)
select
 stg_id
from
 openjson(@json,'$.schoolIds') scl join
 [Справочник школ] sc with (updlock, readpast) on sc.schoolId = a.value join
 stg_student stg on stg.schoolId = sc.schoolId and ISNULL(stg.status,'') <> 'S' 

update [dbo].[stg_student] set status = 'S' 
from [dbo].[stg_student] s
join @studentList sl
on s.stg_id = sl.id

commit tran



Даже если объединить два запроса внутри транзакции как предложил court и установить режим изоляции как repeatable read, у меня не получилось разделить пользователей.

Пользователь 1:
Код: 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.
DECLARE @json varchar(max) =
N'{
"schoolIds": [1, 2]
}'


DECLARE @studentList TABLE (id bigint)

set transaction isolation level repeatable read
begin tran 

update stg 
set stg.status = 'S' 
output inserted.stg_id into @studentList(id)
from stg_student stg 
join openjson(@json,'$.schoolIds') sc on stg.schoolId=value  and ISNULL(transferred_status,'') <> 'S'

waitfor delay '00:00:15'

commit tran
set transaction isolation level read committed


select ss.schoolId, sl.id from @studentList sl
join stg_student ss
on sl.id = ss.stg_id




Пользователь 2:
Код: 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.
DECLARE @json varchar(max) =
N'{
"schoolIds": [2, 3]
}'
select ISJSON(@json)

DECLARE @studentList TABLE (id bigint)

set transaction isolation level repeatable read
begin tran 

update stg 
set stg.status = 'S' 
output inserted.stg_id into @studentList(id)
from stg_student stg 
join openjson(@json,'$.schoolIds') sc on stg.schoolId=value  and ISNULL(transferred_status,'') <> 'S'

waitfor delay '00:00:15'

commit tran
set transaction isolation level read committed


select ss.schoolId, sl.id from @studentList sl
join stg_student ss
on sl.id = ss.stg_id



Оба пользователя получают пересекающиеся данные.
...
Рейтинг: 0 / 0
Параллельная выборка данных двумя или более пользователями
    #39882202
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roust_m,

авторДаже если объединить два запроса внутри транзакции как предложил court и установить режим изоляции как repeatable read, у меня не получилось разделить пользователей.

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


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