sql – 什么是阻止“从TableName与(nolock)选择顶部1 *从返回结果?

前端之家收集整理的这篇文章主要介绍了sql – 什么是阻止“从TableName与(nolock)选择顶部1 *从返回结果?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在运行以下语句
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)

即使这样似乎无限期地运行.我可以理解,如果有数以百万计的记录(*)可能需要很长时间,但我不明白为什么选择前1条记录不会立即回来,考虑到我指定的nolock.

以完全公开的名义,dps_san是通过链接服务器从odbc连接中提取的视图.我不认为这会影响为什么我不能返回顶行,只是把它扔在那里,万一我错了.

所以我想知道什么是保持该声明运行?

编辑:

如上所述,是的,dps_san..savedi_record是一个视图.这是它的作用:

select * from DPS_SAN..root.SAVEDI_RECORD

这只是一个别名,没有分组/排序/等等,所以我不认为问题在这里,但如果我错了,请告诉我.

解决方法

使用NOLOCK的SELECT查询实际上并不采取任何锁定,它们仍然需要在表( and as it is a heap it will also take a hobt lock)上的SCH-S(模式稳定性)锁定.

另外在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

猜你在找的MsSQL相关文章