如何解决 SQL Server 2012 中的死锁错误?

How to solve deadlock error in SQL Server 2012?

我遇到了一个错误

Transaction (Process ID 426) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction

有时我也会收到此错误

Violation of UNIQUE KEY constraint 'UK_UserTotalEntry_VoucherNo'. Cannot insert duplicate key in object 'dbo.UserTotalEntry'. The duplicate key value is (89295/37029)

有时会出现此错误。此外,我已经尝试了很多次,但无法再次生成此错误。我正在尝试借助 datatable 批量插入数据,并在数据库中创建了一个类型化的 table。

我在下面显示我的代码并请求帮助,而且我正在使用 Go daddy 共享主机计划,在该计划中我无法更改我的数据库中的任何内容。提前致谢。

VB.NET代码

Public Function SaveUpdate(ByVal Action As String)
    Dim Msg As String = Nothing

    Try
        Dim dt_bulk As New DataTable
        dt_bulk.Columns.Add("VoucherNo")
        dt_bulk.Columns("VoucherNo").Expression = "'" & lbl_vno.Text & "'"
        dt_bulk.AcceptChanges()

        Dim dt_Update As New DataTable
        dt_Update = dgv_manualentryedit.DataSource

        dt_bulk.Merge(dt_Update)

        If cn.State = ConnectionState.Closed Then cn.Open()

        Dim ds As New DataSet()
        cmd = New SqlCommand("Proc_dml_SaveUpdate")

        cmd.Parameters.AddWithValue("@NumberEntry", dt_bulk)
        cmd.Parameters.AddWithValue("@VoucherNo", lbl_vno.Text)
        cmd.Parameters.AddWithValue("@date", CustomDate(dtp_Date.Value))
        cmd.Parameters.AddWithValue("@GameMasterId", GameMasterID)
        cmd.Parameters.AddWithValue("@ProfitID", ProfitIDNo)
        cmd.Parameters.AddWithValue("@TotalAmt", lbl_mamount.Text)
        cmd.Parameters.AddWithValue("@CreatedBy", LoginID)
        cmd.Parameters.AddWithValue("@Action", Action)
        cmd.Parameters.AddWithValue("@DeviceID", "2")

        cmd.Connection = cn
        cmd.CommandType = CommandType.StoredProcedure
        cmd.CommandTimeout = 9000
        adapter = New SqlDataAdapter(cmd)
        adapter.Fill(ds)

        If DsJantri.Tables.Count = 1 Then
            ds.Tables(0).TableName = "Status"
        Else
            ds.Tables(0).TableName = "PartyDetail"
            ds.Tables(1).TableName = "Status"
        End If
    Catch ex As Exception
        ShowErrorMsg(ex, Me.Name, MethodInfo.GetCurrentMethod().Name)
        Return False
    End Try

    Return True
End Function

我的存储过程

ALTER PROCEDURE [dbo].[Proc_dml_SaveUpdate]
    @NumberEntry NumberEntry READONLY,
    @VoucherNo varchar(50),
    @date varchar(10),
    @GameMasterId int,
    @ProfitID int,
    @TotalAmt int,
    @CreatedBy int,
    @Action Varchar(50),
    @DeviceID varchar(2)
 AS
 BEGIN
     BEGIN TRAN

     SET NOCOUNT ON;      

     BEGIN TRY 
         DECLARE @CrDateTime datetime = CAST(SWITCHOFFSET(SYSDATETIMEOFFSET(), '+05:30') AS datetime) 

         IF @Action = 'Save'
         BEGIN
             INSERT INTO UserTotalEntry (VoucherNo, date, GameMasterId, ProfitID, TotalAmt, CreatedBy, CreatedOn, DeviceID)
             VALUES (@VoucherNo, CONVERT(date, ('' + @date + ''), 103), @GameMasterId, @ProfitId, @TotalAmt, @CreatedBy, @CrDateTime, @DeviceID)
         END
         ELSE IF @Action = 'Update'
         BEGIN
             UPDATE UserTotalEntry 
             SET TotalAmt = @TotalAmt,
                 ModifyOn = @CrDateTime,
                 ModifyBy = @CreatedBy  
             WHERE VoucherNo = @VoucherNo

             DELETE FROM numberentry 
             WHERE VoucherNo = @VoucherNo
         END

         INSERT INTO NumberEntry (VoucherNo, Number, Amount, ID)
             SELECT VoucherNo, Number, Amount, ID 
             FROM @NumberEntry

         UPDATE numberentry  
         SET number = '0' + number 
         WHERE LEN(number) = 1 AND voucherno = @VoucherNo
  
         UPDATE numberentry 
         SET id = 'BB' 
         WHERE LEN(number) = 3  
           AND number <> 100  
           AND ISNULL(id, '') = '' 
           AND voucherno = @VoucherNo

         IF (@@Error <> 0)  
         BEGIN
             ROLLBACK TRANSACTION
         END
         ELSE
             COMMIT TRANSACTION

         SELECT 
             ut.voucherno AS 'VoucherNo', g.GameMasterName,
             u.UserName AS 'AccountName', ut.TotalAmt 
         FROM
             usertotalentry ut  
         LEFT JOIN 
             ProfitnLossAc p ON p.profitid = ut.profitid    
         LEFT JOIN 
             users u ON u.UserId = p.UserId 
         LEFT JOIN 
             gamemaster g ON g.GameMasterId = ut.GameMasterId
         WHERE 
             ut.voucherno = @VoucherNo

         SELECT 'Entry Saved' AS 'Action'
     END TRY  
     BEGIN CATCH  
         IF @@TRANCOUNT > 0
             ROLLBACK TRANSACTION 

         INSERT INTO DbErrorLogs     
             SELECT  
                 ERROR_NUMBER() AS ErrorNumber,
                 ERROR_SEVERITY() AS ErrorSeverity,
                 ERROR_STATE() AS ErrorState,
                 ERROR_PROCEDURE() AS ErrorProcedure,
                 ERROR_LINE() AS ErrorLine,
                 ERROR_MESSAGE() AS ErrorMessage,
                 @CrDateTime AS 'Datetime',
                 @CreatedBy AS LoginID

          SELECT 'Entry Failed' AS 'Action'
    END CATCH;
END

INSERT INTO NumberEntry(凭证编号、编号、金额、ID) SELECT VoucherNo, Number, Amount, ID 来自@NumberEntry

违反了 UNIQUE KEY 约束 'UK_UserTotalEntry_VoucherNo'。无法在对象 'dbo.UserTotalEntry' 中插入重复键。重复键值为 (89295/37029)

请更正您table中计算新行的逻辑,因为唯一键约束它抱怨不允许重复键,当发生时它跳入捕获块首先修复唯一键错误。