【发布时间】:2012-06-30 02:01:45
【问题描述】:
这个问题是关于并发高速插入的。 我必须承认这在我眼中很有趣。
我正在使用 SQL Server 2008 R2 执行 T-SQL 插入和插入触发器之后。
我想确保在插入和插入后触发器之间不会执行任何命令。
使用隔离级别会导致死锁,或者只是不能解决问题。
我正在使用的程序是 Phil 的答案/解决方案 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 次或更少。是的,有时没有开关发生。
一步提高隔离级别无济于事,甚至会导致更多的keys/dependent-keys不时切换。提高两个隔离级别会导致死锁。
降低隔离级别会减少开关,但仍会创建它们。
在每次插入之前开始提高隔离级别并在触发器结束时移回默认隔离级别会导致死锁(在我的实验中,所有插入都没有提交!)。
有人找到出路吗?
如何强制一个insert和它的after insert触发器一起执行,禁止其他insert到同一张表之间?
【问题讨论】:
-
我不清楚 ItemID 是什么或做什么。您可以使用计算列而不是
after触发器来查找它吗? -
另外,在 SQL 2012 中,您可以使用序列。
-
你能告诉我们...
1插入前的表格。2插入自己,以及它们的顺序。3触发器中的代码。 -
@dems - 可以从空表开始(不是必须的)。许多插入试验几乎同时进行。例如,插入包括 RoomID 和 ItemDescription(这是一个下拉列表 - 没有错误,没有代码,没有重要性,我是 null)(忘记 ItemDescription,像
INSERT Rooms (RoomID) VALUES (1)这样的插入并不重要,对于示例。触发代码与源解决方案完全相同:update Rooms set ItemID = (select coalesce(MAX(itemid), 0) + 1 from Rooms r where r.RoomID = inserted.RoomID ) from inserted where Rooms.Id = inserted.Id。就是这样。谢谢。 -
@david-manheim - ItemID 是一个依赖身份。它是同一个 RoomID 的插入序列号。由于权利,顺序很重要。我目前受限于 Sql 2008 R2。谢谢。
标签: sql sql-server sql-server-2008 tsql sql-server-2008-r2