我遇到一个问题,似乎当同一个应用程序的两个不同实例同时运行相同的存储过程时,它会超时,并且想知道我能做些什么来解决它?
我认为问题在于SQL Server 2008处理自身,锁定行和执行SP的方式......我真的不太了解的事情。该应用使用ADODB.Command
来执行SP。
我有一个VB6 exe(App.exe
),在一台服务器上多次运行。这个应用程序调用数据库上的存储过程,返回该应用程序的下一个序列号。此序列号字段对于应用程序实例是唯一的 - 对于正在运行的应用程序的每个实例,表(tbl_SequenceNos
)中有1行。
例如,假设我们已投放:App[a].exe
和App[b].exe
tblSequenceNos
看起来像:
iAppNo| iNextSequenceNo
a | 1234
b | 4567
获取下一个序列号的存储过程相对简单:
CREATE PROEDURE GetNextSequenceNo (@AppNo varchar(1), @NextSequenceNo int output)
AS
BEGIN
DECLARE @TempSequenceNo int
SELECT @NextSequenceNo = iNextSequenceNo
FROM tblSequenceNos
WHERE iAppNo = @AppNo
@NextSequenceNo = @NextSequenceNo + 1
UPDATE tblSequenceNos
SET iNextSequenceNo = @NextSequenceNo
WHERE iAppNo = @AppNo
END
当App[a].exe
和App[b].exe
尝试运行此过程以获取NextSequenceNo
值时,它们会挂起大约30秒(ADO超时?)。
因为每个应用程序从不查看彼此的行,所以我认为这将同时工作而不指定特殊的锁定。有什么我想念的吗?我想也许我需要指定只锁定行,而不是整个表或页面? - 我不知道默认情况下sql2008会做什么。
非常感谢任何帮助! 先感谢您 安德鲁
答案 0 :(得分:2)
您的过程不是线程安全的,并且会产生不正确的结果,因为在select和更新之间,多个线程可能会得到相同的序列nr。
CREATE PROCEDURE GetNextSequenceNo (@AppNo varchar(1), @NextSequenceNo int output)
AS
DECLARE @var table(seq int);
UPDATE tblSequenceNos
SET iNextSequenceNo = @NextSequenceNo + 1
OUTPUT inserted.iNextSequenceNo INTO @var;
WHERE iAppNo = @AppNo
select @NextSequenceNo = seq from @var
GO
还要确保您的iAppNo列已编制索引。 (这意味着仅此列的索引或此字段是索引中第一个字段的索引)