回滚 SQL Server 2012 序列

6

我拥有一个SQL Server 2012序列对象:

/****** Create Sequence Object ******/
CREATE SEQUENCE TestSeq
START WITH 1
INCREMENT BY 1;

我有一个存储过程,它在事务内运行一些查询:

BEGIN TRAN

SELECT NEXT VALUE FOR dbo.TestSeq

<here all the query update code......>

ROLLBACK TRAN

如果交易失败,则所有更新都会回滚,没有问题,但是序列号不会回滚,我猜是因为它超出了事务的范围。对于处理此类情况,有何线索吗?

4
你不能回滚序列,因为它不支持事务。你可以将当前序列存储在一个变量中,在异常块中更改序列。例如:如果出现任何错误,可以执行以下操作:Alter SEQUENCE TestSeq RESTART WITH @var INCREMENT BY 1; - rs.
2
我认为最好保持现状,因为如果我改变顺序,那么在那一刻其他连接会生成下一个值,这会发生什么? - VAAA
是的,你说得对,最好保持原样。 - rs.
4
序列更快(而且生成的锁冲突更少)是因为它们不能回滚。这就是所有数据库管理系统(如 Oracle、PostgreSQL、Firebird、DB2 等)中序列的工作原理。不要担心生成的 ID 中出现“浪费”的值或间隙。 - user330315
2个回答

2

声明一个表来存储所有的序列号,然后使用以下语句:

declare @SequenceNo int

    UPDATE MySequenceNumberTable
    SET @SequenceNo = SequenceNo = SequenceNo + 1
    WHERE SequenceName = 'Your sequence name'

这里单个语句增加值,赋给变量并更新数据库表,因此其原子操作得到保证。由于它是一个简单的数据库更新操作,它在数据库事务中扮演了一部分。如果事务被回滚,则SequenceNo字段值将恢复到其早期值。
唯一的问题是,对于相同序列名称需要下一个值的下一个事务必须等待第一个事务提交或回滚,因为行级锁定。在DB序列的情况下,没有序列的锁定,因此它永远不会阻止需要下一个值的其他事务。
在我们的情况下,我们不能有空缺并且需要并发保护,因此我们使用上述方法,对我们来说运作良好。

1
在处理序列表时,一定要十分小心。它们可能会成为高容量系统中的主要瓶颈,如果你在检索和更新值时不小心,可能会在调用应用程序中出现重复。 - alroc

-4
ROLLBACK语句用于以下方式来取消整个事务:
BEGIN TRANSACTION
...
SQL Statement(s)

...
ROLLBACK TRANSACTION

ROLLBACK 命令也可用以下方式来取消事务的一部分:
BEGIN TRANSACTION
...
SQL Statement(s)

SAVE TRANSACTION savepoint_name

SQL Statement(s)

ROLLBACK TRANSACTION savepoint_name

不太确定你是否理解了问题。 - Andrew Barber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接