Хранимая процедура с контролем параллелизма - PullRequest
0 голосов
/ 26 октября 2019

Я пытаюсь записать хранимую процедуру как SELECT, которая должна сделать заказ на арендуемом доме.

create table rental_house
(
    house_id int identity primary key,
    housename varchar(50),
    adress varchar(100),
    weekno int,
    vacant bit
)

Если дом свободен, его следует забронировать и обновить в weekno.

Если дом забронирован, следует написать код ошибки.

Должен быть контроль параллелизма.

CREATE PROC Booking
    (@house_id INT,
     @weekno INT, 
     @vacant BIT)
AS
BEGIN TRAN
CREATE PROC Booking

as
begin tran
declare @house_id int
select @house_id = house_id

declare @weekno int
select @weekno = weekno

declare @vacant bit
select @vacant = vacant

if (@house_id = house_id) and (@weekno = weekno) and (@vacant <1)
begin
update vacant
set vacant = 0

commit tran
end
else begin
 rollback
 end

1 Ответ

2 голосов
/ 26 октября 2019

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

Один простой способ сделать это - отфильтровать обновление по vacant = 1, а затем проверить @@rowcount после обновления, чтобы увидеть, не повлияло ли оно на какие-либо строки. Например:

update Booking set vacant = 0
where house_id = @house_id
  and week_no = @weekno
  and vacant = 1

if @@rowcount = 0
begin
  throw 50001, 'House not vacant for that week', 1;
end

Если вы отметите vacant в отдельном запросе, вам понадобится явная транзакция и подсказка updlock, чтобы при проверке состояния сеанса получалась и сохранялась блокировка, которая помешала бы другому сеансуизменение статуса, например:

begin transaction

declare @vacant bit = 
  (
     select vacant 
     from Booking with (updlock)
     where house_id = @house_id
        and week_no = @weekno
  )

if @vacant = 1
begin
  update Booking set vacant = 0
  where house_id = @house_id
    and week_no = @weekno
  commit transaction
end
else
begin
    rollback
    throw 50001, 'House not vacant for that week', 1;
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...