Svi*_*ack 2 sql-server identity
我在如下所示的数据库上执行 SQL:
SET IDENTITY_INSERT table1 ON
GO
BEGIN TRANSACTION
GO
INSERT INTO table1 SELECT ... FROM table2
GO
DELETE FROM table2 ...
GO
COMMIT TRANSACTION
GO
SET IDENTITY_INSERT table1 OFF
GO
Run Code Online (Sandbox Code Playgroud)
问题是我的表被锁定在最后一条语句上SET IDENTITY_INSERT table1 OFF
,之前的所有语句大约需要 6 个小时,但我的表现在被锁定在最后一条语句上 1 天。
在活动监视器中,它具有不执行任何命令的连接,但它是锁定链的头部阻塞器,我杀死了它,但没有任何改变,只是处于回滚状态,但它仍在消耗所有 I/O。
我的问题是这个会话在做什么以及如何避免它?由于某种原因,看起来 IDENTITY_INSERT 几乎像全表娱乐一样昂贵,我不知道这会如何导致性能方面的任何缺点。
附加信息:插入期间没有身份冲突,bcs i insert 操作的身份值低于 table1 上的初始设置
餐桌设计:
CREATE TABLE [dbo].[table1] (
[id_table1] BIGINT IDENTITY NOT NULL,
[id_table3] INT NOT NULL,
[some_id] BIGINT NOT NULL,
[some_time2] DATETIME2 NOT NULL,
[some_time] DATETIME2 NOT NULL,
[some_value] FLOAT (53) NOT NULL,
[some_value2] FLOAT (53) NOT NULL,
[some_value3] TINYINT NULL,
CONSTRAINT [FK_table1_table3] FOREIGN KEY ([id_table3]) REFERENCES [dbo].[table3] ([id_table3]),
INDEX [IX_table1] CLUSTERED ([id_table3] ASC, [some_time] ASC, [id_table1] ASC) WITH (DATA_COMPRESSION = PAGE)
) WITH (DATA_COMPRESSION = PAGE);
GO
CREATE INDEX [IX_table1_some_time] ON [dbo].[table1]
([some_time] ASC, [id_table1] ASC) INCLUDE ([id_table3], [some_value], [some_value2], [some_value3]) WITH (DATA_COMPRESSION = PAGE)
GO
Run Code Online (Sandbox Code Playgroud)
SET IDENTITY_INSERT
只是一个会话选项,允许您在后续语句中显式插入标识值。它对事务日志没有任何作用。我认为您的第一笔交易实际上并未提交,现在正在回滚。
如果你有implicit_transactions
,这可能会发生
或者更可能的情况是您已经在不知不觉中进行了公开交易。
如果您的原始脚本在begin tran
和之间包含错误,则可能会发生这种情况commit
。执行然后可以终止执行,留下一个打开的事务(如果你使用了SET XACT_ABORT ON
任何错误,将回滚事务而不是让它保持打开状态。)
然后在修复错误并在同一会话中重新运行脚本后,begin tran
将再次调用并递增@@trancount
,然后COMMIT
将其递减为 1,使事务仍处于打开状态。
在这种情况下,与其终止会话并导致事务回滚,不如做正确的事情(假设您很高兴一切正常,并且原始错误条件没有导致您不想提交的更改),而是检查@@trancount
并commit
根据需要再次执行多次(即在修复错误之前有多次执行的情况下),直到达到零。