2017-05-31 122 views
2

我面对僵局死锁在SQL Server

被死锁的锁资源与另一个进程,并已 选作死锁牺牲品。

问题在SQL-Server中,通过对特定列选择最大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 

任何一个帮助我.....

+0

发生死锁。你必须能够让你的代码更少锁定或简单地处理它们 –

+0

Sir先生我已经提出了一个程序。插入我只是调用该过程返回值,我插入记录。当有不同的用户在同一时间插入数据发生死锁。如果上述商店程序需要更改,我需要帮助。 –

+0

这段代码的重点是什么?如果你想产生序列的数字使用一个SEQUENCE。它在所有支持的SQL Server版本中都可用 –

回答

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 
+0

谢谢先生,让我检查和测试。 –

+0

谢谢你,先生..它的工作.... –

0

呦可以使用序列来避免产生任何阻塞增量值。

我已经改编了我自己的Counter Generator来直接替代你的。它动态创建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 

唯一不方便的是,你的价值观可以在获得差距(因为你可能会检索一个值,但最终没有使用它)。这在我的桌子上不是问题,但你必须考虑它。

+0

谢谢先生。但不幸的是我无法在我的情况下使用你的程序。如果你能帮助我,我会很感激 –

+0

为什么你不能用我的代替你的存储过程?更改名称和参数,并且您的应用程序不会注意到差异。没有办法阻止对原始程序的锁定,因为您需要锁定Maintenance_Counter才能获得重复值。 –

+0

当我们运行您的查询时显示一个错误。Msg 102,Level 15,State 1,Procedure Web_GetMaxColumnID,Line 24 'throw'附近的语法不正确。 –