我的Intranet上有一个页面,它向perl CGI脚本提交请求。该脚本依次调用SQL Server DB上的存储过程,以检查是否存在具有某些属性的对象。如果是,则storproc返回乐器的id,如果不是,则创建一个新乐器并返回该乐器的id。存储过程创建一个事务,并在insert语句中使用with (TABLOCKX)
。为了用户友好性,当所述用户同时提交一堆请求时,网页异步地将请求提交给perl脚本。我认为当提交的所有请求都需要一个新的工具时,第一个命中storproc会运行,锁定表,创建新仪器,释放锁,然后随后对storproc的调用会知道新仪器并使用它。我在实践中看到的是,会有几个请求创建新工具,其余的将使用最新的工具。我尝试在客户端使用setTimeout来隔离请求,但这似乎没有什么区别。关于我可能做错的任何想法?
以下是存储过程的代码:
CREATE PROCEDURE [dbo].[CreateFutures]
@code varchar(5),
@month int,
@year int,
@currency varchar(3)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
declare @ticker varchar(7)
declare @yearCode char(1)
declare @res as Table (id int)
declare @n as int
set @yearCode = convert(char(1), @year % 10)
set @ticker = (
select @code + futures + @yearCode
from FuturesMonthCodes
where month = @month
)
insert into @res
select top 1 instrument
from InstrumentFutures // This is a view that joins InstrumentText and InstrumentNumber data
where ticker = @ticker
and code = @code
and month = @month
and year = @year
and currency = @currency
order by instrument
set @n = (select COUNT(id) from @res)
if @n = 0
begin
print 'Creating Future'
declare @id int
declare @stamp datetime
set @stamp = CURRENT_TIMESTAMP
insert into Instrument with (TABLOCKX) (insertTime) values (@stamp)
set @id = (select SCOPE_IDENTITY());
insert into InstrumentText (instrumentId, name, value) values (@id, 'type', 'futures')
insert into InstrumentText (instrumentId, name, value) values (@id, 'ticker', @ticker)
insert into InstrumentText (instrumentId, name, value) values (@id, 'code', @code)
insert into InstrumentText (instrumentId, name, value) values (@id, 'currency',@currency)
insert into InstrumentNumber (instrumentId, name, value) values (@id, 'month', @month)
insert into InstrumentNumber (instrumentId, name, value) values (@id, 'year', @year)
insert into @res (id) values (@id)
end
commit transaction
if @n = 0 --instrument created
select top 1 id, 1 from @res order by id
else --returning existing instrument
select top 1 id, 0 from @res order by id
END
答案 0 :(得分:1)
这是比perl更多的SQL问题。
假设3个脚本试图在同一时间运行此存储过程。
第一次执行并锁定表。其他人等待表解锁,但是当锁定结束时他们没有重新读取数据,所以他们使用旧数据。
如果您的存储过程进行了选择,则必须在锁定消失后重新运行它。
此致