我有序列表,包含三列:
数,年份,类型
并且每年新的一年都会创建并更新三条新记录。
我生成序列的存储过程在其他存储过程中使用,我的问题是我想阻止对此存储过程的并发访问并将访问作为队列进行访问,因此如果发生并发访问,则必须等待另一个存储过程完成以便两个用户不会获得相同的序列号,代码如下:
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
我读到设置隔离级别可序列化可以解决它,是否足够或者我还必须在存储过程中使用开始和结束事务并手动处理回滚和提交?
答案 0 :(得分:1)
一种方法可能是使用SQL Server应用程序锁,请参阅sp_getapplock和sp_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