我正在运行以下语句
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