SET IDENTITY_INSERT OFF - 导致表锁定

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)

Mar*_*ith 8

SET IDENTITY_INSERT只是一个会话选项,允许您在后续语句中显式插入标识值。它对事务日志没有任何作用。我认为您的第一笔交易实际上并未提交,现在正在回滚。

如果你有implicit_transactions,这可能会发生

或者更可能的情况是您已经在不知不觉中进行了公开交易。

如果您的原始脚本在begin tran和之间包含错误,则可能会发生这种情况commit。执行然后可以终止执行,留下一个打开的事务(如果你使用了SET XACT_ABORT ON任何错误,将回滚事务而不是让它保持打开状态。)

然后在修复错误并在同一会话中重新运行脚本后,begin tran将再次调用并递增@@trancount,然后COMMIT将其递减为 1,使事务仍处于打开状态。

在这种情况下,与其终止会话并导致事务回滚,不如做正确的事情(假设您很高兴一切正常,并且原始错误条件没有导致您不想提交的更改),而是检查@@trancountcommit根据需要再次执行多次(即在修复错误之前有多次执行的情况下),直到达到零。