我有一个INSERT statmenet,它通过在SQL Server 2012
中执行存储过程来获取数据。
INSERT INTO Employee
EXEC tp_GetEmployees
存储过程大约需要30秒才能提供结果。
答案 0 :(得分:2)
INSERT
语句需要在开始执行之前获取必要的稳定锁(或严格地说,作为执行的第一步)。 INSERT
语句包含 EXEC
调用,因此EXEC
作为执行INSERT
的一部分执行,这意味着{{1} }}已经获得了任何必要的稳定性锁(对于INSERT
,这必须至少是一个Intent-Exclusive INSERT
模式,请参阅intent mode locks)。
数据锁是在插入数据时获取的,否则将是不可能的,因为人们不能简单地猜测将在哪些页面上插入哪些键。由于数据由IX
提供,EXEC
无法在实际拥有数据之前锁定正在插入的数据。
有关更多详细信息,您可以实时监控锁定获取和释放,例如。见Using XEVENT in SQL Server。监控这些结果还会显示INSERT
结果是否被缓冲或插入(这是下一个要问的自然问题)。
答案 1 :(得分:1)
在一个查询窗口中,运行以下命令:
create procedure DoLittle
as
WAITFOR DELAY '00:05:00'
select 1 as a
go
create table T (a int not null)
go
insert into T(a)
exec DoLittle
go
在另一个查询窗口中,运行:
sp_lock
哪个应该产生这样的输出(对于运行第一个查询窗口的任何SPID):
spid dbid ObjId IndId Type Resource Mode Status
------ ------ ----------- ------ ---- -------------------------------- -------- ------
54 1 1623676832 0 TAB IX GRANT
也就是说,INSERT ... EXEC
已经占用了一个Intent eXclusive锁。但没有其他锁。没有其他查询能够获得针对表的eXclusive锁,但是他们可能能够获得更低级别的锁。