patternsqlMinor
PAGELATCH_EX occures in update query with UPDLOCK, READPAST
Viewed 0 times
readpastupdatewithqueryupdlockoccurespagelatch_ex
Problem
We have a queue organized with a table on MS SQL Server 2014:
Stored procedure to send message:
And a stored procedure to receive messages:
This stored procedure executes every second to check new messages in queue.
Very often we get blocks (
First idea was - diff-backups, but they are scheduled at different times:
Other queries don't make blocks so often.
CREATE TABLE [queue].[Messages](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Status] [tinyint] NOT NULL,
[Data] [nvarchar](max) NOT NULL,
[CreationDateUtc] [datetime] NOT NULL
)
CREATE NONCLUSTERED INDEX [IX_Messages_Status] ON [queue].[Messages]
([Status] ASC)Stored procedure to send message:
ALTER PROCEDURE [queue].[SendMessage]
@MessageBody NVARCHAR(MAX),
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [queue].[Messages]
(
Data,
)
VALUES
(
@MessageBody,
)
ENDAnd a stored procedure to receive messages:
ALTER PROCEDURE [queue].[ReceiveMessage]
AS
BEGIN
SET NOCOUNT ON;
UPDATE TOP (1) m
SET
m.Status = 2,
m.StartDateUtc = GETUTCDATE()
OUTPUT
INSERTED.*
FROM [queue].[Messages] m WITH (UPDLOCK, READPAST)
WHERE m.Status = 1
ENDThis stored procedure executes every second to check new messages in queue.
Very often we get blocks (
PAGELATCH_EX) on this query even if the queue is empty:First idea was - diff-backups, but they are scheduled at different times:
Other queries don't make blocks so often.
- Am I right that this is due to
UPDLOCKandREADPASThints?
- Are there other reasons?
Solution
This is because you use a Status field for messages and leave unreceiveable messages in the queue. Retaining messages (keeping them after process, with a different status) leads to queue bloat, contention, poor plan choices and general slow processing.
Follow Using tables as Queues and do destructive message processing:
Also drop all indexes on the queue. The linked article has details how to achieve fancier behavior like FIFO or Pending.
Use queues only for events, not for state.
Follow Using tables as Queues and do destructive message processing:
DELETE TOP (1)
FROM [queue].[Messages] m WITH (ROWLOCK, READPAST)
OUTPUT deleted.*;Also drop all indexes on the queue. The linked article has details how to achieve fancier behavior like FIFO or Pending.
Use queues only for events, not for state.
Code Snippets
DELETE TOP (1)
FROM [queue].[Messages] m WITH (ROWLOCK, READPAST)
OUTPUT deleted.*;Context
StackExchange Database Administrators Q#117887, answer score: 4
Revisions (0)
No revisions yet.