IDENTITY_INSERT如何影响并发性?


11

我正在尝试使用第三方第三方SAP附加组件来帮助客户,该附加组件存在发布故障并且已不再支持。

在某些情况下,它将存档和不完整的帖子从发布队列表存档到发布存档表。我需要将这些存档结果移回队列。

队列ID是一个标识列,我希望保持不变。

问题是,如果我关闭了identity_insert on / insert / identity_insert,那么与创建队列条目并期望identity列自动生成的进程的并发性有什么期望?

任何最好的方式来演示这种行为的指针也将不胜感激。

Answers:


8

IDENTITY_INSERT ON单独设置不会消除并发性-这不会在表上放置任何排他锁,而只是简短的架构稳定性(Sch-S)锁。

因此,从理论上讲,在默认行为下,您可以在会话1中进行此操作:

BEGIN TRANSACTION;

-- 1
SET IDENTITY_INSERT dbo.tablename ON;

-- 2
INSERT dbo.tablename(id, etc) VALUES(100, 'foo'); -- next identity is now 101

-- 3
INSERT dbo.tablename(id, etc) VALUES(101, 'foo'); -- next identity is now 102

-- 4
SET IDENTITY_INSERT dbo.tablename OFF;

COMMIT TRANSACTION;

在另一个会话中,您可以在表的第1、2、3或4点处插入行。这似乎是一件好事,除了2到3之间发生的任何插入会发生的情况是触发了自动生成的值另一个会话基于语句2的结果-因此它将生成101,然后语句3将因主键冲突而失败。设置和测试自己非常简单WAITFOR

-- session 1
-- DROP TABLE dbo.what;
CREATE TABLE dbo.what(id INT IDENTITY PRIMARY KEY);
GO
BEGIN TRANSACTION;

SET IDENTITY_INSERT dbo.what ON;

INSERT dbo.what(id) VALUES(32);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(33);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(34);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(35);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(36);

SET IDENTITY_INSERT dbo.what OFF;

COMMIT TRANSACTION;

该批处理开始后,请在另一个窗口中启动该批处理:

-- session 2
INSERT dbo.what DEFAULT VALUES;
WAITFOR DELAY '00:00:01';
GO 20

会话2应该只插入1到20之间的值,对吧?除非由于您的手动插入会话1已更新了基础标识,否则会话2将在会话1中断的地方继续进行,然后插入32或33或34等。这是允许的,但是那么会话1将在下一次插入时因PK违规而失败(一次获胜可能只是时间问题)。

解决此问题的一种方法是TABLOCK在第一个插入上调用一个:

INSERT dbo.what WITH (TABLOCK) (id) VALUES(32);

这将阻止任何其他试图向该表插入(或实际上执行任何操作)的用户,直到您完成将这些归档行移回为止。当然,这会限制并发,但这是您希望阻止工作的方式。希望这不会以如此频繁的速度发生,而您却一直在阻止其他人。

其他一些解决方法:

  • 不再关心IDENTITY产生的价值。谁在乎?如果原始值非常重要,请使用UNIQUEIDENTIFIER(可能是在一个单独的表中生成,并带有IDENTITY一个代理)。
  • 更改存档过程以使用“软删除”,其中某些内容最初标记为已存档,并且直到以后某个日期才将存档永久保存。然后,无论试图将它们移回何处,都可以简单地执行直接更新并修复软删除标志。

谢谢你的解释。我正在编写一个独立的实用程序,以帮助创建这些标识字段的不受支持的产品。我无法控制它的运行方式。
隐喻
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.