SQL Server中的死锁

时间:2017-05-31 06:24:59

标签: sql-server sql-server-2014

我面临死锁

  

在另一个进程的锁资源上死锁了   被选为死锁受害者。

问题在SQL-Server中,我通过对特定列选择max id来在数据库中插入数据,然后添加一个增量,得到将插入记录的值。 我将程序称为下面提到的代码:

CREATE
 PROCEDURE [dbo].[Web_GetMaxColumnID]
 @Col_Name nvarchar(50)        
AS        
BEGIN       
-- SET NOCOUNT ON added to prevent extra result sets from  
 -- interfering with SELECT statements.        
 DECLARE @MaxID BIGINT;              
 SET NOCOUNT ON;   
 -- Insert statements for procedure here        
 BEGIN  
  BEGIN TRAN              
  SET @MaxID = (  
          SELECT Col_Counter  
          FROM   Maintenance_Counter WITH (XLOCK, ROWLOCK)  
          WHERE  COL_NAME = @Col_Name  
      )  

  UPDATE Maintenance_Counter  
  SET    Col_Counter     = @MaxID + 1  
  WHERE  COL_NAME        = @Col_Name  
 COMMIT  
 END      
 SELECT (  
            CONVERT(  
                VARCHAR,  
                (  
                    SELECT office_id  
                    FROM   Maintenance  
                )  
            ) + '' + CONVERT(VARCHAR, (@MaxID))  
        ) AS MaxID  

END

任何人都帮帮我.....

2 个答案:

答案 0 :(得分:1)

正如Marc已经回答的那样,请使用SEQUENCE。它可用于所有受支持的SQL Server版本,即2012及更高版本。避免它的唯一原因是针对像2008这样的不受支持的版本。

在这种情况下,您可以在更新计数器值的同一语句中设置计数器变量。这样,您就不需要任何交易或锁定,例如:

declare @counterValue bigint

UPDATE Maintenance_Counter  
SET    Col_Counter = Col_Counter + 1 , @counterValue=Col_Counter+1
WHERE  COL_NAME        = @Col_Name 

select @counterValue

答案 1 :(得分:0)

Yo可以使用序列生成增量值,避免任何阻塞。

我已将自己的计数器生成器改编为您的直接替代品。它动态创建SQL语句来管理序列,如果序列不存在我们正在寻找的值,它就会创建它。

ALTER PROCEDURE [dbo].[Web_GetMaxColumnID]
    @Col_Name nvarchar(50)
AS
  declare @Value bigint;
  declare @SQL nvarchar(64);
BEGIN
  if not exists(select * from sys.objects where object_id = object_id(N'dbo.MY_SEQUENCES_' + @Col_Name) and type = 'SO') 
  begin
    set @SQL = N'create sequence dbo.MY_SEQUENCES_' + @Col_Name + ' as bigint start with 1';
    exec (@SQL);     
  end

  set @SQL = N'set @Value = next value for dbo.MY_SEQUENCES_' + @Col_Name;      
  exec sp_executesql @SQL, N'@Value bigint out', @Value = @Value out;   

  select @Value ;
END

唯一的不便是你的价值观可能会产生差距(因为你可能已经检索了一个值,但最终没有使用它)。这对我的桌子来说不是问题,但你必须考虑它。