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

我有一个.net事务与SQL插入到MS SQL 2005数据库。 该表具有标识主键。

当事务发生错误时,会调用Rollback()。 行插入被正确回滚,但是当我下一次向表中插入数据时,身份就像从未发生回滚一样递增。 所以基本上在身份序列中存在差距。 有没有办法让Rollback()方法回收失踪的身份?

我不是以正确的方式接近这个吗?

如果你仔细想想,自动递增数字不应该是事务性的。 如果其他交易不得不等待自动编号被使用或“回滚”,则它们将被使用自动编号的现有交易阻塞。 例如,考虑下面的表代码,使用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的自动编号。

这是一个function,而不是一个错误。 我build议使用另一个scheme来生成自动编号,如果你需要它们紧密顺序。

如果你依靠你的身份价值无缝,那么是的 – 你做错了。 代理键的整个意义在于没有商业意义

而且,不,没有办法改变这种行为(缩小自己的自动增量,并且承受阻塞其他插入的性能后果)。

如果您也DELETE了一行,则会在序列中出现空白。

序列必须是唯一的,但不要求是连续的。 他们单调增长的事实只是一种执行而已。

据我所知,插入行索赔自动编号和回滚该数字是失去了好。 如果你依赖于正在sorting的自动编号,你可能要考虑你正在使用的方法。

我不认为有任何要求自动编号的按键顺序。 事实上,我不认为他们可以被要求是:

  • 交易一开始接入
  • 事务b启动并插入
  • 交易中止

    你会得到一个洞。 没有关系。

所有其他海报谁不说担心,你应该得到的差距是正确的。 如果这个数字具有商业意义,而且这个意义不会有差距,那么就不要使用一个标识列。

仅供参考,如果出于任何原因您想要消除这些差距,大多数数据库都有办法将自动编号重新设置为您所select的编号。 这是一个痛苦的屁股,如果你发现自己需要定期做,你绝对不应该使用自动编号/身份领域,如上所述。 但是这里是在SQL服务器中执行的代码:

DBCC CHECKIDENT('Product',RESEED,0)

这将产品表设置为从1开始(尽pipe如果表中有logging,它显然会跳过已经采用的ID值)。其他RDBMS供应商有其自己的语法,但效果大致相同,所以在系统帮助文件或互联网上查找“种子标识”或“重新设置自动编号”。

再次说明:这是针对特殊的场合,而不是经常使用。 不要把它存储在存储过程中,让我们都来到那里。

Muhan试图在执行这个交易的许多同时连接的情况下考虑它,而不是一次一个。 有些会失败,有些会成功。 您希望SQL Server专注于在新请求进入时运行,而不是维护无间隙标识列。 海事组织(价值观的差距)绝对是不值得花时间的东西。

序列实现使用自主事务。 在Oracle中,自治事务曾经是dbms的内部事务,但现在已经暴露给自己使用(而且经常被错误地使用)

 PRAGMA AUTONOMOUS_TRANSACTION;'