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);