1

这个问题是关于并发高速插入的。我必须承认这在我看来很有趣。

我正在使用 SQL Server 2008 R2 执行 T-SQL 插入和插入触发器之后。

我想确保在插入与其后插入触发器之间不会执行任何命令。

使用隔离级别会导致死锁或不能解决问题。

我正在使用的过程是从菲尔到 SQL Server 依赖身份的答案/解决方案 - 有这样的事情吗?

问题是:

有时插入在前一个插入与其后插入触发器之间,导致此结果:

RoomID  ItemID  ItemDescription ID
------  ------  --------------- --
7       1       Door             1
7       2       Window (West)    2
7       3       Window (North)   3
8       1       Door             4
8       2       Table #1         5
8       3       Table #2         6
7       4       Table #1         7
8       4       Chair #1         8
7       6       Table #2         9
7       5       Table #3        10
8       5       Chair #2        11

参见 ID #9 和 #10。Thair ItemID 已切换。ItemID 应该分别是 5 和 6,而不是 6 和 5,但第 10 次插入可能发生在 #9 的后插入触发器完成执行之前。

此问题发生在少于 0.5% 的插入中:2 次开关涉及 4 条记录,插入次数为 1000 次或更少。是的,有时没有开关发生。

一步提高隔离级别无济于事,甚至会导致更多的key/dependent-keys不时切换。提高两个隔离级别会导致死锁。

降低隔离级别会减少开关,但它们仍然会被创建。

在每次插入之前开始提高隔离级别并在触发器结束时移回默认隔离级别会导致死锁(在我的实验中,所有插入都没有提交!)。

有没有人看到出路?

如何强制插入及其后插入触发器一起执行,禁止其他插入到同一张表之间?

4

1 回答 1

5

如何使用而不是插入触发器

当然,您必须自己进行实际插入,但这是 SQL Server 中支持的行为。没有前插入触发器或类似的东西。

无论如何,您仍然可以在此类触发器中使用当前的触发器处理逻辑。

为了尝试想象一个更好的解决方案,您能解释一下您要做什么吗?此表中是否插入了多个线程?这是一个实时过程吗?

就像拍卖一样。是的,该表中插入了多个线程。问题在后面,但发生了。还没有抱怨的理由,但可能有(现在发生的转变不是在关键点)。发起插入的用户需要知道他们在订单列表中的优先级。ItemID 几乎立即使用,因此,可能不会在稍后需要几毫秒时即时计算(使用 select count(*)... where..)。错误的ItemID顺序可能会导致一个人的损失和另一个人的不正当收益。

好吧,多线程插入在 SQL Server 中几乎从来都不是一个好主意。至少不是没有某种同步。

你需要某种排队。例如,我有一个类似的系统,每天需要插入 2.5-3 百万条记录(嗯,工作时间)。

起初我还使用 8-16 个线程直接在数据库上进行插入。我注意到了这种行为:死锁。所以我开始考虑如何将这些消息排队,以便随时插入 1 个线程(1 个连接)。

我最终在 MSMQ(事务性)中对这些记录进行了排队。其他一些过程从这里(也是事务性的)来并把它们分批插入到数据库中。我的记录保证以正确的顺序出现,也就是发送它们的顺序。

因此,这个辅助过程会插入成批的记录,并且像您一样,我需要在插入之前进行一些预处理,我正在使用而不是插入触发器来执行此操作。在那里,我可以“安静地”更新整个inserted表格,而不必担心有人会来弄乱我的东西。

这只是一个想法。您可能还需要考虑使用 Service Broker 进行排队,特别是如果您不想在 SQL Server 之外进行处理。

此外,值得尝试的是具有快照隔离级别和行版本控制的事务,但我建议采用 MSMQ/Service Broker 方式。

于 2012-06-29T15:37:32.853 回答