1

我有由三列组成的序列表:

编号、年份、类型

并且对于每个新年,今年都会创建和更新三个新记录。

我用于生成序列的存储过程在其他存储过程中使用,我的问题是我想阻止对该存储过程的并发访问并将访问作为队列进行,因此如果发生并发访问,则必须等待另一个完成,以便两个用户没有得到相同的序列号,代码如下:

ALTER PROCEDURE [dbo].[GETSEQUENECENO]
@p_hijricYear                             INT ,
@p_typeId                                 INT ,
@return_val                               INT OUTPUT 
AS 
BEGIN
DECLARE @newSequence                              INT 

BEGIN TRY
SELECT @return_val  = 0
SELECT @newSequence  =  ISNULL( max(correspondencenumber) ,0 )
FROM  io_sequencenumbers with (XLOCK)  
WHERE
hijricyear  = @p_hijricyear
AND
typeid  = @p_typeid
END TRY

BEGIN CATCH
SELECT @newSequence  = -1 
END CATCH

IF @newSequence != -1
BEGIN


IF @newSequence = 0 
BEGIN 
SELECT @newSequence  = 1 
INSERT INTO  io_sequencenumbers    
VALUES 
( @newSequence , 
@p_hijricYear , 
@p_typeId )  
END

ELSE
BEGIN 
SELECT @newSequence  = @newSequence + 1 
UPDATE  io_sequencenumbers   
SET
correspondencenumber = @newSequence 
WHERE  hijricyear  = @p_hijricyear
AND
typeid  = @p_typeid 
END

END -- end of @newSequence!= -1 --

SELECT @return_val = @newSequence
END

我读到将隔离级别设置为可序列化可以解决它,这是否足够或者我还必须在存储过程中使用开始和结束事务并手动处理回滚和提交?

4

2 回答 2

1

我能够以这种方式优化序列生成:

ALTER PROCEDURE [dbo].[GETSEQUENECENO]
@p_hijricYear                             INT ,
@p_typeId                                 INT ,
@return_val                               INT OUTPUT 
AS 
BEGIN
DECLARE @newSequence                              numeric(18,0) 





BEGIN TRY
UPDATE  IO_SEQUENCENUMBERS WITH (READCOMMITTEDLOCK)
SET     @newSequence = correspondencenumber = correspondencenumber + 1
WHERE
hijricyear  = @p_hijricyear
AND
typeid  = @p_typeid
END TRY

BEGIN CATCH
SELECT @newSequence  = -1 
END CATCH

SELECT @return_val = @newSequence

END
于 2015-02-08T09:38:40.990 回答
1

一种方法是使用 SQL Server 应用程序锁,请参阅sp_getapplocksp_releaseapplock。这将允许您通过 SP 序列化您的序列生成,而无需可序列化事务,但不会阻止其他代码访问 io_sequecenumbers 表,因此您需要确保此 SP 是更新此表的唯一位置。

于 2015-02-03T07:50:23.140 回答