防止在sql server中并发访问存储过程

时间:2015-02-03 07:12:29

标签: sql-server stored-procedures sql-server-2012 database-locking

我有序列表,包含三列:

数,年份,类型

并且每年新的一年都会创建并更新三条新记录。

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

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

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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