3

我正在 SQL Server (2008 R2) 中实现一个队列,其中包含要执行的作业。完成后,作业将移至历史表,设置成功或失败标志。队列表中的项目有一个标识列作为主键。历史队列具有此 id 和时间戳的组合作为 PK。

如果作业失败,我希望选择重新运行它,并且他们认为这是将其从历史记录表移回实时队列。出于可追溯性的目的,我希望重新插入的行具有与原始条目相同的 ID,这会导致问题,因为这是一个标识列。

我看到两种可能的解决方案:

1) 使用 IDENTITY_INSERT:

SET IDENTITY_INSERT TableName ON

-- Move from history to live queue

SET IDENTITY_INSERT TableName OFF

2) 创建一些自定义逻辑来生成唯一 ID,例如从实时队列和历史队列中获取最大 ID 值并添加一个。

我没有看到 2 有任何真正的问题,除了它很乱,可能性能很差,而且它让我神经质的皮肤爬行......

选项 1 我喜欢,但我不太清楚其中的含义。这将如何表现?而且我知道同时对两张桌子这样做会使事情崩溃和燃烧。如果两个线程同时对同一张表执行此操作会发生什么?

对于半常用的存储过程来说,这是否是一种很好的方法,或者这种技术是否应该只用于在蓝月亮中批量插入数据?

关于哪个是最好的选择,或者有更好的方法有什么想法吗?

4

4 回答 4

1

我会选择选项 1 - 使用IDENTITY_INSERT

SET IDENTITY_INSERT TableName ON

-- Move from history to live queue

SET IDENTITY_INSERT TableName OFF

IDENTITY_INSERT是适用于当前连接的设置 - 因此,如果另一个连接正在执行类似操作,则不会产生任何影响。使用它时出现错误的唯一地方是,如果您尝试将其设置ON在另一张桌子上而没有先OFF在第一张桌子上打开它。

于 2011-05-18T06:57:25.447 回答
0

您不能使用原始(实时)身份值插入历史记录表吗?你说你无论如何都要将它与时间戳结合起来。

于 2011-05-18T06:46:04.187 回答
0

假设队列的标识列是分配“作业 ID”的列,我认为最简单的解决方案是添加一个新的“原始作业 ID”可为空的列,可能 FK 指向历史表。然后,当您重新运行作业时,允许它在添加到队列时获取新 ID,但让它在此新列中保留对原始作业的引用。

要回答“或者是否应该将此技术仅用于在蓝月亮中批量插入数据一次”,我会说是的,当然,这正是它的用途。


糟糕,@Damien_The_Unbeliever 是对的,我忘记了IDENTITY_INSERT设置是每个连接的。使用身份插入方法让自己陷入真正的麻烦会很复杂(我猜会像 MARS 一样,或者错误处理错误)。尽管如此,我认为尝试重用 ID 是一个错误!

于 2011-05-18T06:51:55.517 回答
0

在重用标识值时,我可以看到一个潜在的性能问题,即标识列是否由聚集索引编制索引。

A strict growing number will cause inserted rows to always be added last in the clustered index and no page splits will occur.

If you start to insert reused numbers then you may cause page splits during those insertions. If that is a problem is up to your domain.

于 2011-05-18T11:29:33.413 回答