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

13

我在 SQL Server 2008 中有一个视图 V,它基本上是查看表 AB 的内容。

create view V as
    select * from A
    union all
    select * from B

V中读取会导致查询对基本表采取意向共享锁(IS lock),但也会在视图对象本身上采取意向共享锁(IS lock)

很明显为什么我们需要在表上使用IS锁,我们可以看到,在视图上的IS锁可以防止对视图底层基础表的并发修改。这很好。

查询计划中没有提到视图,它完全被编译掉了,因此在这种情况下生成的计划只是来自两个基本表的简单行拼接。实际上,查询计划XML中唯一提到的视图是在语句文本中。

如果您在这些表上添加第二个视图U,则从V中读取不会对U采取任何锁。这排除了引擎在AB上所有视图中都采用IS锁的可能性。

数据库引擎如何知道在视图上采取锁?

  • 语句文本是否再次解析?
  • 查询规划器和底层执行之间是否有其他信息通道传递此信息?

有关详细信息,请参见dba.stackexchange上的相应问题


大概是通过锁定视图来防止在使用视图时进行设计更改。 - JamieSee
@JamieSee,那就需要一个S或Sch-M锁。 - usr
1
执行计划被存储为二进制格式。并不是所有信息都在我们看到的 XML 中展示出来。 - Martin Smith
@MartinSmith 我认为这可能是答案。存储引擎知道锁定视图的机制的详细信息可以被认为是内部的,但它执行此操作的事实是用户可见的,我期望它在某个地方有文档记录。 - Joe Kearney
3个回答

4

我的dba.stackexchange答案复制:

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

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

注意:从一个版本到另一个版本的内部情况不能保证一致。这在官方支持的表面区域之下。

我的信念是执行计划的二进制版本(而不是通过XML可读和公开的子集)必须包含指向原始查询文本中引用的视图的某些指针(上面已经提到过这一点)。显然,它不会每次解析查询文本。Conor以上暗示了这一点,但小心翼翼地没有透露任何关于存储位置或方式的细节,因为这可能会随着发布版本、服务包或累积更新而发生变化。他可能也不想鼓励任何侦探工作。 :-)


2
如果你查看sys.dm_exec_query_optimizer_info视图,该视图返回SQL Server查询优化器的细节信息,其中一个返回的细节是以下字段:

视图引用 - 视图在查询中被引用的次数。

似乎追踪了视图被引用的次数,可能作为执行计划的一部分...我的假设是即使视图被展开,执行计划仍然包含了使用哪些视图的详细信息,并针对这些引用的视图发出适当的IS锁。

1
如果有一个单独的数据结构来处理这些依赖关系,那么当相关对象被修改时,就不必扫描整个计划缓存区了。不过我认为这种内部细节可能没有任何文档记录。 - Martin Smith
@MartinSmith 我认为你是对的...就像你在问题评论中提到的那样,这些依赖项可以包含在执行计划的二进制文件中。我搜索了一段时间,这个DMV是我能找到的唯一涉及该主题的参考资料。 - Michael Fredrickson
@MichaelFredrickson 嗯,这是一个不错的开始,感谢你找到了它。我真的很想知道是否有文档记录了对视图进行锁定,并且特别地,我认为这不应该被视为内部实现细节。相反,所采取的锁定似乎是通过视图读取的语义的可见部分。 - Joe Kearney

0

默认情况下,视图会像宏一样展开到引用它们的查询中。

这可以关闭,或者根据需要进行材料化等变化,但类似宏的内联展开是常态。这意味着锁定等行为就好像您执行了以下操作...

SELECT
  *
FROM
  blah
INNER JOIN
(
  yourViewCode
)
  AS aView
    ON aView.id = blh.id

1
但它并没有像这样表现。 - usr
2
这可能是一个很好的便利,以便理解,但视图在创建时编译。如果基础表发生更改,则默认情况下视图不会更改。特别是出于这个原因,您应该避免在视图中使用“select *”。 - Gordon Linoff
@Dems 我知道视图是这样扩展的,我不是在谈论超出这个规范或实现视图的行为。无论如何,正如usr指出的那样,那不是我所问的行为。 - Joe Kearney
尽管在视图中使用select *语句有其优点,但显然这只是视图的一个简单方便的示例 - 这与问题无关。 - Joe Kearney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接