Sql server 基于特定条件生成唯一的连续序列号,无需使用TABLOCKX
每次向我的客户发送消息时,都会在名为“确认”的表中插入一个新条目。在插入过程中,我需要获取当天发送给特定客户的确认“SequenceNumber”列的最大值。该SequenceNumber随后递增1,并用于新记录 约束是为了确保在一天中为发送到同一客户机的确认生成连续的唯一序列号 我已经能够使用可序列化隔离级别和TABLOCKX提示实现这一点。此解决方案可以工作,但不能提供最佳的并发性能。您知道如何实现此解决方案以提供更好的性能吗 当前解决方案(封装在存储过程中)Sql server 基于特定条件生成唯一的连续序列号,无需使用TABLOCKX,sql-server,locking,sequence,isolation-level,database-concurrency,Sql Server,Locking,Sequence,Isolation Level,Database Concurrency,每次向我的客户发送消息时,都会在名为“确认”的表中插入一个新条目。在插入过程中,我需要获取当天发送给特定客户的确认“SequenceNumber”列的最大值。该SequenceNumber随后递增1,并用于新记录 约束是为了确保在一天中为发送到同一客户机的确认生成连续的唯一序列号 我已经能够使用可序列化隔离级别和TABLOCKX提示实现这一点。此解决方案可以工作,但不能提供最佳的并发性能。您知道如何实现此解决方案以提供更好的性能吗 当前解决方案(封装在存储过程中) 在serializable中,
在
serializable
中,您不需要任何提示。引擎为您提供了串行执行。在这里,这相当于锁定SequenceNumber
的现有索引中的最后一行。这基本上是可行的,但您需要重试死锁
我会用这个:
SELECT @SequenceNumber = MAX (SequenceNumber)
FROM dbo.Confirmation WITH (UPDLOCK, HOLDLOCK, ROWLOCK)
WHERE ...
为此,您不需要任何特定的隔离级别,因为
HOLDLOCK
强制序列化。这几乎总是无死锁的(几乎是因为引擎没有做出正式的保证)。您好,谢谢您的回复。我通过删除SET隔离级别SERIALIZABLE并使用表UPDLOCK、HOLDLOCK、ROWLOCK提示应用了您的解决方案。该解决方案似乎运行良好,并不会生成重复的序列号。我还将SELECT MAX语句嵌套在INSERT指令中,以便将整个内容呈现为原子。感谢您,声明不会导致任何事情是原子的,只有事务和锁定。合并语句没有任何影响。您是否建议我在解决方案中绝对需要使用BEGIN TRAN和COMMIT TRAN,以获得预期的行为?如果只有一条语句,则它周围将有一个隐式事务,但对于并发事务来说,它不一定是原子事务。我不确定你现在的最终代码是什么。如果您仍在使用serializable,则保证整个事务都是原子的。;如果您以前没有事务,那么合并语句确实会产生影响,因为它使两个语句都成为同一事务的一部分。这是真的。
SELECT @SequenceNumber = MAX (SequenceNumber)
FROM dbo.Confirmation WITH (UPDLOCK, HOLDLOCK, ROWLOCK)
WHERE ...