在执行任何其他插入之前,如何强制插入触发器在插入之后执行?

时间:2012-06-29 15:26:45

标签: sql sql-server sql-server-2008 tsql sql-server-2008-r2

此问题与并发高速插入有关。 我必须承认,在我看来它非常有趣。

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

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

使用隔离级别会导致死锁或只是 NOT 解决问题。

我正在使用的程序是菲尔的答案/解决方案 SQL Server dependent Identity - is there such a thing?

问题是:

有时插入介于前一个插入和插入后触发之间,导致此结果:

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个插入或更少。是的,有时候没有出现开关。

将隔离级别提高一步无济于事,甚至会导致更多键/从属键不时切换。提高两个隔离级别会导致死锁。

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

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

有没有人看到出路?

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

1 个答案:

答案 0 :(得分:5)

如何使用instead of insert trigger

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

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

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

  

像拍卖一样。是的,此表中插入了多个线程。   问题是后方但发生了。没有理由抱怨,但是   可能会有(这些开关发生在现在不在关键时刻   点)。启动插入的用户需要知道他们是什么   订单列表中的优先顺序。 ItemID几乎迫在眉睫,   因此,可能无法即时计算(选择计数(*)...   其中..)稍后需要时毫秒。错误的顺序   ItemID可能导致一方损失,另一方可能造成非合法收益。

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

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

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

我最终在MSMQ(事务性)中排队这些记录。其他一些进程来自这里(也是事务性的)并将它们分批插入数据库中。我的记录保证按照正确的顺序排列,即发送它们的顺序。

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

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

此外,值得尝试的是与Snapshot Isolation level and row versioning的交易,但我建议采用MSMQ / Service Broker方式。