【发布时间】:2018-04-28 23:37:00
【问题描述】:
我想通过使用 insert into 从存储过程返回一个输出。出于性能原因,目标表是内存优化表类型。 我现在发现,当存储过程运行时,存储过程中所有受影响的行都保持锁定,直到存储过程完成。
例子:
insert into @ModifiedSecurities (SecurityID, AttributeTypeID)
exec Securities.spSecuritiesImportBody
@ProcessingID = @ProcessingID
在执行Securities.spSecuritiesImportBody 期间(最多需要10 分钟),所有受spSecuritiesImportBody 影响的表行都被锁定,直到存储过程完成(甚至这些表都与存储过程的输出无关)。
虽然在单个插入语句中这种行为可能有意义,但我看不到它有任何用途,因此想摆脱这些锁。
有没有办法在不创建这些锁的情况下执行存储过程?
这是我制作的代码示例:
- 执行准备工作
- 运行代码
- 在代码运行时尝试从 dbo.ProcessingsTesting 中进行选择。这是不可能的,因为桌子被锁定了。在 dbo.UpdProcessing 期间正在创建锁。但是,由于某种原因,锁没有被释放。
选择 * 来自 dbo.ProcessingsTesting
--准备开始
drop procedure dbo.UpdProcessing
drop table dbo.ProcessingsTesting
drop procedure dbo.spSecuritiesImportBody
go
create table dbo.ProcessingsTesting
(
ProcessingID int,
EndDate datetime
)
insert into dbo.ProcessingsTesting
(
ProcessingID
)
select 1 union all
select 2 union all
select 3 union all
select 4 union all
select 5
-- stored procedure
go
create procedure dbo.spSecuritiesImportBody
(
@ProcessingID int
)
as
begin
exec dbo.UpdProcessing
@ProcessingID = @ProcessingID
WAITFOR DELAY '00:03:00'
-- return data
select 1, 2
end
-- stored procedure
go
create procedure dbo.UpdProcessing
(
@ProcessingID int
)
as
begin
update dbo.ProcessingsTesting
set EndDate = null
where ProcessingID = @ProcessingID
end
--准备结束
-- run the code
declare @ModifiedSecurities table
(
[SecurityID] [int] NOT NULL,
[AttributeTypeID] [smallint] NOT NULL
)
insert into @ModifiedSecurities (SecurityID, AttributeTypeID)
exec dbo.spSecuritiesImportBody
@ProcessingID = 1
【问题讨论】:
-
显示存储过程的代码,可能有一个事务覆盖了整个事情,需要调整得更细。
-
如果源是基于磁盘的,您可以分离阶段。有一个阶段从 SNAPSHOT 隔离级别的基于磁盘的表中读取,将结果推送到中间表。然后,将中间结果推送到内存优化表。我希望您可以执行跨容器 SNAPSHOT 事务,但您不能。在这种情况下,我已经多次成功使用此方法。
-
不买锁不释放。这个例子肯定不会锁定其他表。
标签: sql sql-server tsql stored-procedures sql-server-2016