【问题标题】:Identity column SQL Server 2005 inserting same value twice标识列 SQL Server 2005 两次插入相同的值
【发布时间】:2018-11-11 06:37:39
【问题描述】:

我有一个插入到表中的存储过程(其中有一个不是主键的标识列 - 最初使用日期/时间插入 PK 以生成唯一值)。

然后我们使用 SCOPEIDENTITY() 来获取插入的值,然后有一些逻辑根据这个值生成主键字段值,然后更新回表。

在某些情况下,存储过程被多个进程同时调用,导致“违反 PRIMARY KEY 约束...”错误。

这似乎表明标识列允许为多个记录插入相同的数字。

第一个问题 - 这怎么可能?

第二个问题 - 如何停止它...目前没有错误处理,所以我将添加一些 try/catch 逻辑 - 但想完全理解问题以便正确处理

【问题讨论】:

  • 永远不要使用日期时间作为 PK,重复很容易获得!!!这只是时间问题,双关语!

标签: sql sql-server-2005 identity-column


【解决方案1】:

仔细查看错误信息:

违反PRIMARY KEY约束...

鉴于你说过:

如果有一个标识列不是主键 - 最初使用日期/时间插入 PK 以生成唯一值

在我看来,问题与标识列无关,因为它不是主键,但日期/时间方法更可能生成唯一值并且尝试插入时失败。

您不只是使用标识列作为主键是否有某些原因?

【讨论】:

  • 可能是初始主键生成是问题(时间使用到毫秒,因此必须在完全相同的毫秒发生)。我认为第二代主键值更有可能是问题(这意味着用于这一代的标识列值是问题)数据库模式来自现有应用程序,可能是这部分您会考虑遗留的应用程序!- 不知道最初决定的原因
  • 系统时钟返回的时间通常只能精确到大约。在大多数计算机上为 15 毫秒,因此插入只需在相同的 15 毫秒周期内发生,而不是相同的毫秒;如果有可能在这个边距内发生两次插入(每秒只有大约 65 次插入),那么我希望从初始密钥生成中看到错误。
  • 这真的很有趣,谢谢 Greg...在这种情况下,我建议分配给开发人员的路线可能还不够。也许使用 guid 而不是时间生成初始密钥会更好......
【解决方案2】:

我认为,您应该改用 IDENT_CURRENT('tablename')

SCOPE_IDENTITY(),将返回当前会话中创建的最后一个身份值。

IDENT_CURRENT不受范围和会话限制;它仅限于指定的表。

http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/

在这里您可以了解您的问题

http://web.archive.org/web/20130605142906/http://connect.microsoft.com/SQLServer/feedback/details/328811/

还有一篇关于并行的有用文章

https://sqlblog.org/2009/03/21/six-reasons-you-should-be-nervous-about-parallelism

祝你好运!

【讨论】:

  • 感谢您的链接。在我看来,使用 IDENT_CURRENT 可以确保问题更频繁地发生,而不是修复它——无论当前运行的存储过程的范围如何,它都会将最后一个插入到我的表中——但这就是我试图避免的。阅读链接,我想问题可能不是身份列插入,而是使用 SCOPE_IDENTITY() 读回。我需要完全了解问题发生的环境,看看并行性是否是原因。感谢您的帮助
  • 这看起来很可能目前 - 将尝试在插入中使用 OUTPUT 子句而不是 SCOPE_IDENTITY() 的链接之一上使用建议的解决方法之一。会告诉你进展如何/再次感谢
  • 好的,如果我发现任何其他问题,我也会更新我的答案。祝你好运!
  • 我们为我们的 SQL 服务器关闭并行性:sqlcat.com/top10lists/archive/2008/10/01/… 和:feodorgeorgiev.com/blog/2010/03/…
【解决方案3】:

最初使用日期/时间插入 PK 以生成唯一值

您确定是身份造成了问题吗?如果您插入当前日期/时间值作为 PK 的初始值,并且它同时由 2 个不同的线程/进程同时执行,那么您可能会获得相同的值。

【讨论】:

  • 是的,这是可能的。日期/时间用于毫秒,因此 2 个存储过程的执行必须在完全相同的毫秒内发生
猜你喜欢
  • 2021-08-03
  • 1970-01-01
  • 2010-09-18
  • 1970-01-01
  • 1970-01-01
  • 2014-10-28
  • 1970-01-01
  • 2016-10-18
  • 2013-08-02
相关资源
最近更新 更多