SQL Server 如何知道锁定视图对象?

Joe*_*ney 6 sql-server-2008 sql-server view locking

不确定这是否或多或少适合提出这个问题,最初是在Stack Overflow 上提出的。


在SQL Server 2008中我有一个观点V在表AB看起来大致是

create view V as
    select * from A
    union all
    select * from B
Run Code Online (Sandbox Code Playgroud)

读取V导致查询在基表上获取意图共享锁,但也会在视图对象本身获取意图共享锁

很明显为什么我们需要表上的 IS 锁,并且我们可以看到视图上的 IS 锁阻止了对视图底层表的并发修改。没关系。

查询计划没有提及视图。它是完全编译出来的,在这种情况下生成的计划是来自两个基表的行的简单串联。实际上,查询计划 XML 中唯一提到的视图是在语句文本中。

如果您U在表上添加第二个视图,则读取V不会导致任何锁定U。这排除了引擎只对A和上的所有视图进行 IS 锁定B

数据库引擎如何知道锁定视图?

  • 语句文本是否再次解析?
  • 查询规划器和底层执行之间是否有其他一些信息通道来传递这些信息?如果是这样,是什么?

如果是后者,存储引擎知道锁定视图的机制的细节可以被认为是内部的。然而,它这样做的事实是用户可见的,我希望它在某处被记录下来。

Aar*_*and 5

来自 Conor Cunningham,与引擎或优化器相关的任何事物的最终来源:

我们在编译期间跟踪事物以在运行时检查。为此,我们不会在执行时解析事物。

注意:我们不能保证从一个版本到另一个版本所做的内部工作。这是在官方支持的表面积之下。

我的信念是执行计划的二进制版本(不是可读并通过 XML 公开给我们的那个,它只是二进制版本的一个子集)必须包含一些指向原始查询中引用的视图的指针文本(这在 SO 问题中有所提及)。它显然不是每次都解析查询文本。Conor 暗示了上述内容,但注意不要透露有关其存储位置或方式的任何详细信息,因为这可能会随着版本的不同而发生变化,甚至可能会随着服务包或累积更新而变化。他可能也不想鼓励任何侦探工作。:-)


Pau*_*ite 5

好问题。虽然视图定义在编译和优化过程中早就被扩展到查询文本中,但所有类型的信息都使用不直接可见的缓存计划进行跟踪,例如被认为对计划探索“有趣”的统计数据,这样我们就可以在这些统计数据发生变化时获得预期的重新编译。即使最终选择的计划形状没有直接使用更改的统计数据,情况也是如此——我们仍然应该重新编译,因为现在可能有更好的计划可用。

同样,用户会合理地期望“使用”视图应该阻止任何并发尝试更改该视图的定义。即使实现在任何真正的编译或优化发生之前扩展了视图文本,这也应该是正确的。为此,视图object_id应该是缓存计划的一部分,并且在每次执行该计划时采用一个非常兼容的 Intent-Shared 锁是有意义的。持有这个锁可以防止另一个会话在该对象上获取 Sch-M(模式修改)并在我们逻辑引用它时修改视图(即使它被扩展)。显然,锁定视图引用的对象是不够的。

关于是否应该记录此类事情的问题。多年来 Books Online 的形态表明,记录某些东西意味着它必须经过一个弃用循环才能更改,因此除非明显的政策发生变化,因此“文档”被扩展为包括“有趣的细节,但可能会改变在任何时候',这种内部实现细节似乎不太可能成为正式文档。