在并发中实现序列号

时间:2014-06-03 00:12:37

标签: sql sql-server

我是事务隔离级别的新手。我也是SQL的初学者。 我有两个存储过程,如下所示。

  create PROCEDURE [dbo].[spupdaterecordinfintab]
      @IDS BIGINT
  AS
     BEGIN
begin try
begin transaction

declare @id bigint
set @id = (select [Seedno] from [dbo].[SeedNo] where [Type] = 'abc')+1
DECLARE @INUM NVARCHAR(50) 
SET @INUM = 'ABC'+ CAST(@id AS nvarchar(20))

UPDATE [dbo].[exchTab]
SET 
    [INUMBER] = @INUM

    WHERE [id] = @IDS

UPDATE [dbo].[SeedNo]
SET
  [Seedno] = @id
WHERE [Type] = 'INV'

EXEC spNEWROECORDINTOfintab @IDS
commit
end try
begin catch
    rollback transaction

end catch

    END


create PROCEDURE [dbo].spNEWROECORDINTOfintab 
   @IDS BIGINT
AS
BEGIN    
    declare @id bigint
    set @id = (select [Seedno] from [dbo].[SeedNo] where [Type] = 'abc')+1

    DECLARE @INUM NVARCHAR(50) 
    SET @INUM = 'ABC'+ CAST(@id AS nvarchar(20))

    insert into [dbo].[exchTab]
    values( @INUM,123.78,1)

    UPDATE [dbo].[SeedNo]
    SET [Seedno] = @id
    WHERE [Type] = 'INV'
END

我希望在我的exchTab tbale中获得inumber中的序列号。多个用户执行时如何实现此目的 [spupdaterecordinfintab]存储过程同时(并发)?哪种事务隔离级别适合?

由于

1 个答案:

答案 0 :(得分:0)

我通常在SELECT指令中使用如下代码,强制对其进行独占锁定:

create PROCEDURE [dbo].spNEWROECORDINTOfintab 
@IDS BIGINT
AS
BEGIN
    BEGIN TRANSACTION
    declare @id bigint
    SELECT @id = [Seedno] from [dbo].[SeedNo] WITH (ROWLOCK, XLOCK) where [Type] = 'abc'
    SET @id = @id + 1
    DECLARE @INUM NVARCHAR(50)
    SET @INUM = 'ABC'+ CAST(@id AS nvarchar(20))

    insert into [dbo].[exchTab]
    values( @INUM,123.78,1)

    UPDATE [dbo].[SeedNo]
    SET
       [Seedno] = @id
    WHERE [Type] = 'INV'
    COMMIT TRANSACTION
END

此过程中有两个关键部分。第一个是第一个SELECT,其中包含ROWLOCKXLOCK提示。那些告诉数据库引擎对受影响的行施加独占锁(而不是读取的默认共享锁)。这会阻止此指令上的任何其他并发进程,迫使它们等待proc完成。 ROWLOCK仅阻止实际的行读取,由WHERE子句选择。请注意,要使其正常工作,您需要在该列上使用唯一索引,否则您将最终锁定整个表。

另一个重要的部分是交易管理。我在开头添加了BEGIN TRANSACTION,在结尾添加了COMMIT TRANSACTION。原因是锁只在交易期间持有。如果省略,每个陈述都构成了自己的交易,因此其他读者可以弄乱表格并获得重复/跳过的数字。