Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 как решить задачу блокировки?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
есть процедура, которая делает следующие действия
begin tran
select from t where flag = 0

update t set flag = 1
commit tran

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

Как решить проблему?
11 июл 11, 16:32    [10956895]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Glory
Member

Откуда:
Сообщений: 104751
update ... output
11 июл 11, 16:34    [10956906]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
update + output + select
11 июл 11, 16:35    [10956926]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
воттак
Guest
Winnipuh
есть процедура, которая делает следующие действия
begin tran
select from t where flag = 0

update t set flag = 1
commit tran

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

Как решить проблему?


т.е если будет 10 записей в таблице t c полем flag=0
то она обновит все 10 записей?
11 июл 11, 16:46    [10956984]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
воттак
Winnipuh
есть процедура, которая делает следующие действия
begin tran
select from t where flag = 0

update t set flag = 1
commit tran

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

Как решить проблему?


т.е если будет 10 записей в таблице t c полем flag=0
то она обновит все 10 записей?


поймал

нет, это упростил

скажем так:

select top 1 @id=id from t where flag=0 and ....
update from t where @id=id
11 июл 11, 17:56    [10957513]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
в реальной процедуре идут проверки, выборки из всяких вью, потом определяется
ид записи и ей меняется флаг.

begin tran
if @par1 <>2
begin
  select ...
  select @id=id from ...
  ...
end
else
begin
  select ...
  select @id=id from ...
  ...
end

update t set flag=1 where id=@id;
commit tran
11 июл 11, 18:07    [10957632]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Andrey Sribnyak
Member

Откуда: Киев
Сообщений: 600
Winnipuh,


use test
go
if OBJECT_ID ('t21') is not null 
	drop table dbo.t21
go
	
create table dbo.t21 (id int identity (1,1), flag bit)

go


declare @i int =0
declare @imax int =100

while @i<=@imax
	begin
		insert into dbo.t21 values (0)
		set @i=@i+1
	end
go	



begin tran
	declare @id int =0
	select top 1 @id=id from dbo.t21 WITH (TABLOCKX) where flag=0 order by id


и пока не пройдет commit пытаемся в ДРУГОЙ сессии выполнить

begin tran
	declare @id int =0
	select top 1 @id=id from dbo.t21  WITH (TABLOCKX) where flag=0 order by id
	select @id
	

а затем делаем commit в первой сессии
11 июл 11, 18:16    [10957694]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Шыфл
Member

Откуда: Прага
Сообщений: 776
Winnipuh,

хотя бы так
begin tran
update t set flag = -@@SPID

--bla-bla-bla

select from t where flag = -@@SPID

update t set flag = 1 where flag=-@@SPID

commit tran

Хотя лучше табличку-очередь организовать, с тригером обработки...
11 июл 11, 18:16    [10957698]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Шыфл
Member

Откуда: Прага
Сообщений: 776
первая выборка другая, конечно же
update t set flag = -@@SPID where flag = 0
11 июл 11, 18:20    [10957718]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2680
Шыфл, Andrey Sribnyak,

Как всё сложно...
А так - не проще? И операция атомарная, и транзакции не надо.

update t set flag = 1
OUTPUT deleted.*
from t where flag = 0
11 июл 11, 18:54    [10957876]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Andrey Sribnyak
Member

Откуда: Киев
Сообщений: 600
Makar4ik
Шыфл, Andrey Sribnyak,

Как всё сложно...
А так - не проще? И операция атомарная, и транзакции не надо.

update t set flag = 1
OUTPUT deleted.*
from t where flag = 0


Так ему еще на второй минуте обсуждения посоветовали :-)
11 июл 11, 19:00    [10957909]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Andrey Sribnyak
Makar4ik
Шыфл, Andrey Sribnyak,

Как всё сложно...
А так - не проще? И операция атомарная, и транзакции не надо.

update t set flag = 1
OUTPUT deleted.*
from t where flag = 0


Так ему еще на второй минуте обсуждения посоветовали :-)


у меня проверки сложнее, я выше написал.
Т.е чтобы определить ид записи, которую вернуть и которйо имзенить флаг, мне надо сделать несколько выборок из вью и только потом уже апдейт
11 июл 11, 19:03    [10957925]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Crimean
Member

Откуда:
Сообщений: 13147
для любителей 2000 сиквела в селект ставим XLOCK, READPAST )
11 июл 11, 19:04    [10957932]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2680
Andrey Sribnyak
Так ему еще на второй минуте обсуждения посоветовали :-)
Ну да. Так ровно это ему и было нужно.
11 июл 11, 19:04    [10957935]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Crimean
для любителей 2000 сиквела в селект ставим XLOCK, READPAST )


в селект из трехэтажных вью, и заблокирует тучу таблиц..
11 июл 11, 19:09    [10957961]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2680
Winnipuh
у меня проверки сложнее, я выше написал.
Т.е чтобы определить ид записи, которую вернуть и которйо имзенить флаг, мне надо сделать несколько выборок из вью и только потом уже апдейт

в один запрос проверки - не запихнуть?
update t1 set flag = 1
OUTPUT deleted.*
from t1 inner join t2 on t1.ID=t2.id
inner join .....
where t1.id = 
CASE WHEN @par1 <> 2 THEN ....
ELSE ...
END
11 июл 11, 19:16    [10957983]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Шыфл
Member

Откуда: Прага
Сообщений: 776
Makar4ik
Winnipuh
у меня проверки сложнее, я выше написал.
Т.е чтобы определить ид записи, которую вернуть и которйо имзенить флаг, мне надо сделать несколько выборок из вью и только потом уже апдейт

в один запрос проверки - не запихнуть?


Ты же не знаешь, что у него там за выборки. Может, там два вагона логики насыпано? Я такое очередью решаю.

П.с. select @@version так и не прозвучало
11 июл 11, 19:29    [10958029]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Шыфл
Makar4ik
пропущено...

в один запрос проверки - не запихнуть?


Ты же не знаешь, что у него там за выборки. Может, там два вагона логики насыпано? Я такое очередью решаю.

П.с. select @@version так и не прозвучало


2005-2008R2
11 июл 11, 19:42    [10958068]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Makar4ik
Winnipuh
у меня проверки сложнее, я выше написал.
Т.е чтобы определить ид записи, которую вернуть и которйо имзенить флаг, мне надо сделать несколько выборок из вью и только потом уже апдейт

в один запрос проверки - не запихнуть?
update t1 set flag = 1
OUTPUT deleted.*
from t1 inner join t2 on t1.ID=t2.id
inner join .....
where t1.id = 
CASE WHEN @par1 <> 2 THEN ....
ELSE ...
END


сделал так, почти так, т.е. изменил output into @t и в критерии where id in (select ...)
и после апдейта выбрал

select * from @t

так вот интересный эффект: пустил параллельно два вызова, первый вернул
с flag=0, все хорошо, а второй вернул ту же запись, но уже flag=1

Совсем странно...
11 июл 11, 20:06    [10958119]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2680
Winnipuh
так вот интересный эффект: пустил параллельно два вызова, первый вернул
с flag=0, все хорошо, а второй вернул ту же запись, но уже flag=1

Совсем странно...

Ничего странного, если в запросе пропущено условие Where flag = 0...
11 июл 11, 20:15    [10958144]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Makar4ik
Winnipuh
так вот интересный эффект: пустил параллельно два вызова, первый вернул
с flag=0, все хорошо, а второй вернул ту же запись, но уже flag=1

Совсем странно...

Ничего странного, если в запросе пропущено условие Where flag = 0...


есть там условие, я же свой запрос использую, первый вызов вернул именно по такому критерию запись.

т.е. выходит, что заворачивание селекта в подзапрос апдейта не решает такого типа проблему, тот же эффект...
особенность в том, что селект выполняется несколько секунд, я накидал данных... вот и эффект...
11 июл 11, 20:18    [10958155]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2680
Winnipuh
Makar4ik
пропущено...

Ничего странного, если в запросе пропущено условие Where flag = 0...


есть там условие, я же свой запрос использую, первый вызов вернул именно по такому критерию запись.

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

Не... Так быть не должно...
Хотя... А какой ISOLATION LEVEL?
11 июл 11, 20:27    [10958172]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Шыфл
Member

Откуда: Прага
Сообщений: 776
Winnipuh,

Бугагашеньки :) Ставлю на READ COMMITTED, ибо default.
11 июл 11, 20:32    [10958183]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Шыфл
Winnipuh,

Бугагашеньки :) Ставлю на READ COMMITTED, ибо default.


дефолт иссессно
11 июл 11, 20:34    [10958186]     Ответить | Цитировать Сообщить модератору
 Re: как решить задачу блокировки?  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2680
Winnipuh
Шыфл
Winnipuh,

Бугагашеньки :) Ставлю на READ COMMITTED, ибо default.


дефолт иссессно
хе-хе...
SERIALIZABLE в помощь!
11 июл 11, 20:36    [10958194]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить