什么是阻止从返回结果“从表名与(NOLOCK)选择顶部1 *”?(What's blocki

2019-07-29 19:32发布

我目前正在运行下面的语句

select * into adhoc..san_savedi from dps_san..savedi_record

它采取了痛苦的很长一段时间,我想看到多远沿就这样我跑了这一点:

select count(*) from adhoc..san_savedi with (nolock)

这并没有及时所以它赫克我这样做返回任何东西:

select top 1 * from adhoc..san_savedi with (nolock)

即使是似乎无限期地运行。 我能理解,如果有几百万的COUNT(*)可能需要很长的时间记录,但我不明白,为什么选择顶部1记录不会回来几乎立即考虑到我指定NOLOCK。

在完全公开的名称,dps_san是,从通过链接服务器ODBC连接拉的图。 我不认为这会是影响我为什么不能返回前行,但只是把它扔在那里的情况下,我错了。

所以,我想知道什么是保持该语句运行?

编辑:

正如我上面提到的,是dps_san..savedi_record是一个视图。 下面介绍一下它的作用:

select * from DPS_SAN..root.SAVEDI_RECORD

这只不过是一个别名以上,但没有分组/排序/等,所以我不认为问题就出在这里,但请大家指教我,如果我错了。

Answer 1:

SELECT与查询NOLOCK不采取实际没有锁,他们仍然需要SCH-S架构稳定性)上表锁( 并且因为它是一个堆也将采取hobt锁 )。

另外之前SELECT甚至可以开始SQL Server必须编译一个计划的声明,这也要求其采取SCH-S锁在桌子上。

当你的长期运行的事务通过创建表SELECT ... INTO它拥有一个不兼容的SCH-M上的锁,直至语句完成。

您可以通过查看验证这个sys.dm_os_waiting_tasks封闭期间的时间段,而 一段时间

当我试图在一个连接以下

BEGIN TRAN

SELECT *
INTO NewT
FROM master..spt_values

/*Remember to rollback/commit this later*/

然后执行(或者只是试图查看估计执行计划)

SELECT *
FROM NewT
WITH (NOLOCK)

在第二读取查询被封堵。

SELECT wait_type,
       resource_description
FROM sys.dm_os_waiting_tasks
WHERE session_id = <spid_of_waiting_task>

显示等待类型确实SCH_S和阻塞资源SCH-M

wait_type        resource_description
---------------- -------------------------------------------------------------------------------------------------------------------------------
LCK_M_SCH_S      objectlock lockPartition=0 objid=461960722 subresource=FULL dbid=1 id=lock4a8a540 mode=Sch-M associatedObjectId=461960722


Answer 2:

它很好可能是没有锁......如果dps_san..savedi_record是一个视图,那么它可能会花费很长的时间来执行,因为它可能会访问表,而不使用索引,也可能是数以百万计的排序记录,或任何原因。 然后你的查询,甚至一个简单的顶部或计数,将只有尽可能快地这一观点可以被执行。



Answer 3:

有几个问题需要考虑这里。 被dps_san..savedi_record一个看法? 如果是的话,它可能只是采取了很长一段时间,让您的数据。 我能想到的另一件事是,你试图通过创建一个临时表select into语法,这是一个坏主意。 select * into ...语法将锁定在tempdb的选择的持续时间。

如果你正在使用的语法创建表,然后有一个解决方法。 首先,通过投掷创建表where 1=0 ,在你最初的语句结尾:

select * into ... from ... where 1=0

这将首先创建表(快速),它允许你insert into ,因为该表现在存在(无锁tempdb数据库查询的持续时间的罚款)。



Answer 4:

找到session_id正在执行select into

SELECT r.session_id, r.blocking_session_id, r.wait_type, r.wait_time
  FROM sys.dm_exec_requests AS r
  CROSS APPLY sys.dm_exec_sql_text(r.plan_handle) AS t
  WHERE t.[text] LIKE '%select%into%adhoc..san_savedi%';

这应该让你知道,如果另一个会话阻塞到选择或者如果它有一个等待类型,是造成问题。

您可以重复这一过程在另一个窗口正在试图做的选择会话。 我怀疑马丁是对的,我先前有关架构锁注释是相关的。



文章来源: What's blocking “Select top 1 * from TableName with (nolock)” from returning a result?