Skip to main content
added 391 characters in body
Source Link
Charlieface
  • 14.5k
  • 14
  • 40

Your queries are deadlocking on range locks, which can be a wide lock, but in theory a range lock can be avoided completely here, by ensuring you only lock a single row.

It seems some kind of query notification is involved, possibly using SqlDependency or similar. Exactly what query was passed for the notification is not clear, but it seems to be affected by the statements in your procedure. Whether or nor improving the locking in the procedure will help, I don't know, but you should do it anyway. We really need to see that other notification query.

Firstly, your query can be improved by removing the self-join, and instead updating the subquery directly.

CREATE PROCEDURE [dbo].[usp_AddLineNotification]
    @ID_ORGLEVELVALUE INT,
    @ReuestType NVARCHAR(250),
    @NotificationMessage NVARCHAR(2000)=NULL
AS

SET NOCOUNT, XACT_ABORT ON;   -- need XACT_ABORT for proper error handling

BEGIN TRAN;
                   
UPDATE t
    SET CreatedDate = GETUTCDATE(),       
        NotificationMessage = @NotificationMessage
    FROM (
        SELECT TOP (1) *
        FROM TBL_ABC WITH (UPDLOCK) 
        WHERE NotificationRequest = @ReuestType 
          AND ID_OrgLevelValue = @ID_ORGLEVELVALUE
        ORDER BY ID DESC
    ) t;
                    
IF @@ROWCOUNT = 0
BEGIN
    INSERT INTO TBL_ABC (NotificationRequest, ID_OrgLevelValue, CreatedDate, NotificationMessage) 
    VALUES (@RequestType, @ID_ORGLEVELVALUE, GETUTCDATE(), @NotificationMessage);
END;

COMMIT TRAN;

Secondly, you need to add ID to the ordering of the NC index to support this query properly. You also need to add the two columns you are modifying as INCLUDE columns.

CREATE NONCLUSTERED INDEX [IX_FK_Mast_OrgLevelValue] 
ON [dbo].[TBL_ABC]
(ID_OrgLevelValue, NotificationRequest, ID)
INCLUDE (CreatedDate, NotificationMessage)
    WITH (DROP_EXISTING = ON);

Your queries are deadlocking on range locks, which can be a wide lock, but in theory a range lock can be avoided completely here, by ensuring you only lock a single row.

Firstly, your query can be improved by removing the self-join, and instead updating the subquery directly.

CREATE PROCEDURE [dbo].[usp_AddLineNotification]
    @ID_ORGLEVELVALUE INT,
    @ReuestType NVARCHAR(250),
    @NotificationMessage NVARCHAR(2000)=NULL
AS

SET NOCOUNT, XACT_ABORT ON;   -- need XACT_ABORT for proper error handling

BEGIN TRAN;
                   
UPDATE t
    SET CreatedDate = GETUTCDATE(),       
        NotificationMessage = @NotificationMessage
    FROM (
        SELECT TOP (1) *
        FROM TBL_ABC WITH (UPDLOCK) 
        WHERE NotificationRequest = @ReuestType 
          AND ID_OrgLevelValue = @ID_ORGLEVELVALUE
        ORDER BY ID DESC
    ) t;
                    
IF @@ROWCOUNT = 0
BEGIN
    INSERT INTO TBL_ABC (NotificationRequest, ID_OrgLevelValue, CreatedDate, NotificationMessage) 
    VALUES (@RequestType, @ID_ORGLEVELVALUE, GETUTCDATE(), @NotificationMessage);
END;

COMMIT TRAN;

Secondly, you need to add ID to the ordering of the NC index to support this query properly. You also need to add the two columns you are modifying as INCLUDE columns.

CREATE NONCLUSTERED INDEX [IX_FK_Mast_OrgLevelValue] 
ON [dbo].[TBL_ABC]
(ID_OrgLevelValue, NotificationRequest, ID)
INCLUDE (CreatedDate, NotificationMessage)
    WITH (DROP_EXISTING = ON);

Your queries are deadlocking on range locks, which can be a wide lock, but in theory a range lock can be avoided completely here, by ensuring you only lock a single row.

It seems some kind of query notification is involved, possibly using SqlDependency or similar. Exactly what query was passed for the notification is not clear, but it seems to be affected by the statements in your procedure. Whether or nor improving the locking in the procedure will help, I don't know, but you should do it anyway. We really need to see that other notification query.

Firstly, your query can be improved by removing the self-join, and instead updating the subquery directly.

CREATE PROCEDURE [dbo].[usp_AddLineNotification]
    @ID_ORGLEVELVALUE INT,
    @ReuestType NVARCHAR(250),
    @NotificationMessage NVARCHAR(2000)=NULL
AS

SET NOCOUNT, XACT_ABORT ON;   -- need XACT_ABORT for proper error handling

BEGIN TRAN;
                   
UPDATE t
    SET CreatedDate = GETUTCDATE(),       
        NotificationMessage = @NotificationMessage
    FROM (
        SELECT TOP (1) *
        FROM TBL_ABC WITH (UPDLOCK) 
        WHERE NotificationRequest = @ReuestType 
          AND ID_OrgLevelValue = @ID_ORGLEVELVALUE
        ORDER BY ID DESC
    ) t;
                    
IF @@ROWCOUNT = 0
BEGIN
    INSERT INTO TBL_ABC (NotificationRequest, ID_OrgLevelValue, CreatedDate, NotificationMessage) 
    VALUES (@RequestType, @ID_ORGLEVELVALUE, GETUTCDATE(), @NotificationMessage);
END;

COMMIT TRAN;

Secondly, you need to add ID to the ordering of the NC index to support this query properly. You also need to add the two columns you are modifying as INCLUDE columns.

CREATE NONCLUSTERED INDEX [IX_FK_Mast_OrgLevelValue] 
ON [dbo].[TBL_ABC]
(ID_OrgLevelValue, NotificationRequest, ID)
INCLUDE (CreatedDate, NotificationMessage)
    WITH (DROP_EXISTING = ON);
Post Migrated Here from stackoverflow.com (revisions)
Source Link
Charlieface
  • 14.5k
  • 14
  • 40

Your queries are deadlocking on range locks, which can be a wide lock, but in theory a range lock can be avoided completely here, by ensuring you only lock a single row.

Firstly, your query can be improved by removing the self-join, and instead updating the subquery directly.

CREATE PROCEDURE [dbo].[usp_AddLineNotification]
    @ID_ORGLEVELVALUE INT,
    @ReuestType NVARCHAR(250),
    @NotificationMessage NVARCHAR(2000)=NULL
AS

SET NOCOUNT, XACT_ABORT ON;   -- need XACT_ABORT for proper error handling

BEGIN TRAN;
                   
UPDATE t
    SET CreatedDate = GETUTCDATE(),       
        NotificationMessage = @NotificationMessage
    FROM (
        SELECT TOP (1) *
        FROM TBL_ABC WITH (UPDLOCK) 
        WHERE NotificationRequest = @ReuestType 
          AND ID_OrgLevelValue = @ID_ORGLEVELVALUE
        ORDER BY ID DESC
    ) t;
                    
IF @@ROWCOUNT = 0
BEGIN
    INSERT INTO TBL_ABC (NotificationRequest, ID_OrgLevelValue, CreatedDate, NotificationMessage) 
    VALUES (@RequestType, @ID_ORGLEVELVALUE, GETUTCDATE(), @NotificationMessage);
END;

COMMIT TRAN;

Secondly, you need to add ID to the ordering of the NC index to support this query properly. You also need to add the two columns you are modifying as INCLUDE columns.

CREATE NONCLUSTERED INDEX [IX_FK_Mast_OrgLevelValue] 
ON [dbo].[TBL_ABC]
(ID_OrgLevelValue, NotificationRequest, ID)
INCLUDE (CreatedDate, NotificationMessage)
    WITH (DROP_EXISTING = ON);