在不使用 TABLOCKX 的情况下,根据特定条件生成唯一的连续序列号
Generate unique contiguous sequence number based on specific criteria without using TABLOCKX
每次向我的客户发送消息时,都会在名为 'Confirmation' 的 table 中插入一个新条目。在插入期间,我需要获取白天发送给我的特定客户的确认的 'SequenceNumber' 列的最大值。然后此 SequenceNumber 递增 1 并用于新记录。
约束是为了确保为当天发送给同一客户的确认生成连续的唯一序列号。
我已经能够使用 Serializable 隔离级别和 TABLOCKX 提示来实现它。该解决方案有效,但在并发性方面没有提供最佳性能。知道如何实施此解决方案以提供更好的性能吗?
当前解决方案(封装在存储过程中)
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT @SequenceNumber = MAX (SequenceNumber)
FROM dbo.Confirmation WITH (TABLOCKX)
WHERE DATEDIFF(dd, CreationDate, @creationDate) = 0 AND
ClientId = @recipientId
IF (@SequenceNumber IS NULL)
SET @SequenceNumber = 1
ELSE
SET @SequenceNumber = @SequenceNumber+1
INSERT INTO Confirmation (...) VALUES (..., @SequenceNumber, ...)
COMMIT TRAN
在 serializable
你不需要任何提示。该引擎为您提供了类似串行执行的功能。在这里,这相当于为 SequenceNumber
锁定了希望存在的索引中的最后一行。这基本上有效,但您需要死锁重试。
我会用这个:
SELECT @SequenceNumber = MAX (SequenceNumber)
FROM dbo.Confirmation WITH (UPDLOCK, HOLDLOCK, ROWLOCK)
WHERE ...
为此您不需要任何特定的隔离级别,因为 HOLDLOCK
强制可序列化。这几乎总是没有死锁(几乎是因为引擎没有做出正式保证)。
每次向我的客户发送消息时,都会在名为 'Confirmation' 的 table 中插入一个新条目。在插入期间,我需要获取白天发送给我的特定客户的确认的 'SequenceNumber' 列的最大值。然后此 SequenceNumber 递增 1 并用于新记录。
约束是为了确保为当天发送给同一客户的确认生成连续的唯一序列号。
我已经能够使用 Serializable 隔离级别和 TABLOCKX 提示来实现它。该解决方案有效,但在并发性方面没有提供最佳性能。知道如何实施此解决方案以提供更好的性能吗?
当前解决方案(封装在存储过程中)
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT @SequenceNumber = MAX (SequenceNumber)
FROM dbo.Confirmation WITH (TABLOCKX)
WHERE DATEDIFF(dd, CreationDate, @creationDate) = 0 AND
ClientId = @recipientId
IF (@SequenceNumber IS NULL)
SET @SequenceNumber = 1
ELSE
SET @SequenceNumber = @SequenceNumber+1
INSERT INTO Confirmation (...) VALUES (..., @SequenceNumber, ...)
COMMIT TRAN
在 serializable
你不需要任何提示。该引擎为您提供了类似串行执行的功能。在这里,这相当于为 SequenceNumber
锁定了希望存在的索引中的最后一行。这基本上有效,但您需要死锁重试。
我会用这个:
SELECT @SequenceNumber = MAX (SequenceNumber)
FROM dbo.Confirmation WITH (UPDLOCK, HOLDLOCK, ROWLOCK)
WHERE ...
为此您不需要任何特定的隔离级别,因为 HOLDLOCK
强制可序列化。这几乎总是没有死锁(几乎是因为引擎没有做出正式保证)。