Met*_*hor 12 sql-server-2005 sql-server insert identity
我正在尝试使用 3rd 方 SAP 附加组件帮助客户,该附加组件有发布故障并且已停止支持。
在某些情况下,它会将发帖队列表中未完成的帖子归档到发帖存档表。我需要将这些存档的结果移回队列中。
队列 ID 是一个身份列,我想保持不变。
问题是,如果我执行 identity_insert on/insert/identity_insert off,对于创建队列条目并期望自动生成标识列的进程的并发性,我可以期待什么?
任何有关演示此类行为的最佳方式的指针也将不胜感激。
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;
Run Code Online (Sandbox Code Playgroud)
在另一个会话中,您可以在点 1、2、3 或 4 处向表中插入行。这似乎是一件好事,除了在 2 和 3 之间发生的任何插入会触发自动生成的值另一个会话基于语句 2 的结果 - 因此它将生成 101,然后语句 3 将因主键冲突而失败。使用一些WAITFORs设置和测试自己非常简单:
-- 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;
Run Code Online (Sandbox Code Playgroud)
该批次开始后,在另一个窗口中启动该批次:
-- session 2
INSERT dbo.what DEFAULT VALUES;
WAITFOR DELAY '00:00:01';
GO 20
Run Code Online (Sandbox Code Playgroud)
会话 2 应该只插入 1-20 的值,对吗?除了因为您的手动插入会话 1 已更新了底层身份之外,会话 2 将在某个时候从会话 1 停止的地方开始,并插入 32、33 或 34 等。它将被允许这样做,但是然后会话 1 将在下一次插入时失败,并出现 PK 违规(哪个获胜可能只是时间问题)。
解决此问题的一种方法是TABLOCK在第一次插入时调用 a :
INSERT dbo.what WITH (TABLOCK) (id) VALUES(32);
Run Code Online (Sandbox Code Playgroud)
这将阻止任何其他用户尝试使用此表插入(或执行任何操作),直到您完成将这些归档行移回。这当然会限制并发性,但这是您希望阻塞工作的方式。希望这不会以如此频繁的速度发生,您一直在阻止其他人。
一些其他解决方法:
IDENTITY产生的价值。谁在乎?如果原始值非常重要,则使用 a UNIQUEIDENTIFIER(可能在单独的表中生成并IDENTITY作为代理)。| 归档时间: |
|
| 查看次数: |
3078 次 |
| 最近记录: |