即使事务回滚,SQL身份(自动编号)也会增加


78

我有一个带有SQL插入SQL Server 2005数据库的.net事务。该表具有一个身份主键。

当事务内发生错误时,将Rollback()被调用。行插入将正确回滚,但是,下次我将数据插入表时,身份将增加,就好像从未发生过回滚一样。因此,本质上在同一性序列中存在缺口。有什么方法可以使该Rollback()方法回收丢失的身份?

我不是用正确的方法吗?


摘要编辑:将“自动编号”更改为“身份”。自动编号是MS Access术语,而身份是SQL Server中的专有术语。
瑞克

尚未将帖子标记为答案?您还在等待“您的答案”吗?
康坎

2
票数最高的答案会尝试进行零尝试,以实际回答避免这种行为的问题。不管方法正确与否。
杰夫·斯文森

Answers:


105

如果您考虑一下,则自动递增号不应是事务性的。如果其他事务必须等待以查看是否要使用或“回滚”自动编号,则使用该自动编号的现有事务将阻止它们。例如,考虑下面我的表A的伪代码,对ID列使用一个自动编号字段:

User 1
------------
begin transaction
insert into A ...
insert into B ...
update C ...
insert into D ...
commit


User 2
-----------
begin transaction
insert into A ...
insert into B ...
commit

如果用户2的事务在用户1的事务之后一毫秒开始,那么他们向表A的插入将不得不等待用户1的整个事务完成,以查看是否使用了从第一次插入A的自动编号。

这是一个功能,而不是错误。如果您需要自动编号,我建议使用另一种方案来生成自动编号。


启动SQL Server 2012的序列功能可能有助于创建紧密的序列号-simple-talk.com/sql/learn-sql-server/sql-server-sequence-basics
RBT

34

如果您依靠自己的身份价值观是无懈可击的,那么可以-您做错了。一个整点代理键来是有没有商业意义

而且,没有,没有办法改变这种行为(缺少滚动您自己的自动增量,并且遭受阻塞其他插入物的性能后果)。


16

如果您DELETE连续一行,也会在序列中出现缺口。

序列必须是唯一的,但不必是序列的。它们单调增加的事实只是实现的偶然。


6

据我所知,要插入的行声明了自动编号,并且在回滚时该编号永远丢失了。如果您依赖于自动编号的排序方式,则可能需要考虑使用的方法。


6

其他所有不担心的海报发布者,应该避免差距,这都是对的。如果数字具有商业意义,并且该意义不存在空白,则不要使用标识列。

仅供参考,如果出于某种原因您想消除差距,大多数数据库都可以将自动编号重新设置为您选择的编号。这很麻烦,如果您发现自己需要定期进行此操作,则绝对不应该使用自动编号/身份字段,如上所述。但是以下是在SQL Server中执行此操作的代码:

DBCC CHECKIDENT('产品',RESEED,0)

这会将product表设置为从1开始(尽管如果表中有记录,显然它会跳过已获取的ID值。)其他RDBMS供应商也有自己的语法,但是效果大致相同,因此,请在系统帮助文件或互联网中查找“种子身份”或“种子自动编号”。

再次:这是在特殊场合,而不是经常使用。不要将其放在存储过程中,不要让我们所有人都来。


6
在我看来,仅在删除测试数据以准备实时数据时才使用种子。几乎从来没有在生产系统上使用过。
HLGEM,2009年

3
尽管如果表中有记录,显然它将跳过已经获取的ID值”-我的经验是,事实并非如此,当您尝试执行INSERT(在SQL Server 2008上测试)。您需要将其重新设置为表中的最大标识值。它将在下一个INSERT上分配下一个值(即预递增)。
samgak

4

我不认为自动编号的键必须是连续的。实际上,我认为不要求它们是:

  • 事务a开始并插入

  • 事务b开始并插入

  • 交易中止

    你有一个洞。与它无关。


1

Muhan试图在执行此事务的多个同时连接而不是一次执行的情况下考虑它。有些会失败,有些会成功。您希望SQL Server专注于在新请求进入时运行它们,而不是维护无间隙的身份列。IMO它(价值差距)绝对不值得花时间。


1

不会。序列实现使用自治事务。在Oracle中,自治事务曾经是dbms的内部事务,但是现在公开给您自己使用(并且经常被错误地使用)

PRAGMA AUTONOMOUS_TRANSACTION;' 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.