SQL Server里的闩锁耦合(Latch Coupling)
几年前,我写了篇关于闩锁和为什么SQL Server需要它们的文章。在今天的文章里,我想进一步谈下非缓存区闩锁(Non-Buffer Latches),还有在索引查找操作期间,SQL Server如何使用它们。在这里你会学到称为闩锁耦合(Latch Coupling)的概念。
索引查找操作(Index Seek Operations)
正如你知道的,SQL Server使用扫描(Scan)和查找(Seek)操作在索引(聚集和非聚集索引)里访问数据。这里的查找操作使用B树的导航结构在叶子节点查找特定的记录。下图展示了这个概念。
在这个例子里,SQL Server读取索引根页,在层级下的索引页,最后在叶子级别读取数据页。每次SQL Server在缓存池里访问这个页,这个页需要获得共享闩锁(Shared Latch)。共享闩锁是至关重要的,因为在内存里,它让当下处理的页只读:
- 每个排它闩锁(Exclusive Latch)和共享闩锁不兼容。
因此请求一个排它闩锁会阻塞,SQL Server会提示你有个PAGELATCH_EX等待类型。
现在我们来看下在查找操作期间,在索引页上,SQL Server如何获取和释放这些闩锁。下列代码展示了对于一个特定的会话ID,可以捕获latch_acquired和latch_released事件的扩展事件会话(根据实际情况修改会话ID)。
CREATE EVENT SESSION LatchTracking ON SERVER
ADD EVENT sqlserver.latch_acquired
(
ACTION
(
sqlserver.database_id,
sqlserver.session_id,
sqlserver.sql_text
)
WHERE
(
[package0].[equal_uint64]([sqlserver].[session_id],(54)) AND [class]=(28))
),
ADD EVENT sqlserver.latch_released
(
ACTION
(
sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text
)
WHERE
(
[package0].[equal_uint64]([sqlserver].[session_id],(54)) AND [class]=(28))
)
ADD TARGET package0.event_file
(
SET filename=N'c:\temp\LatchTracking.xel'
)
WITH
(
MAX_MEMORY = 4096 KB,
EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
MAX_DISPATCH_LATENCY = 30 SECONDS,
MAX_EVENT_SIZE = 0 KB,
MEMORY_PARTITION_MODE = NONE,
TRACK_CAUSALITY = OFF,
STARTUP_STATE = OFF
)
GO
注意:在“class”属性上的筛选谓语限制了缓存闩锁。它们的内部ID是28。是的,扩展事件是自表述的……
下一步,我现在用一个表来进行聚集索引查找操作,在那个表上我已经创建了聚集索引,在导航层级里包含三层(包含叶子层)。
闩锁耦合实战(Latch Coupling in Action)
扩展事件会话向你展示了,在聚集索引查找操作期间,对于整个会话需要那个缓存闩锁(只要你修改的会话ID是正确的……)。当你查看输出时,你会看到我们已经捕获了6个事件:3个latch_acquired事件, 和3个latch_released事件。
但更有意思的事是SQL Server获得和释放这些闩锁的顺序。一般你期望SQL Server在页上获得闩锁,并最后释放这个闩锁。但事实并非如此!
我们来详细看下。首先SQL 在索引根页(975号页)上获得了一个共享闩锁。在SQL Server处理那个页后,聚集索引查找操作在接下来的层级里,继续读取请求的页,并在它上面获取闩锁(257号页)。
注意在索引根页上获得的闩锁还没有释放,它还保持获取!
当在接下来的索引页上成功获取闩锁后,在索引根页上的闩锁才会释放。这个方法称为闩锁耦合(Latch Coupling)。这个必须的,因为SQL Server在B树结构里,跟随从一个页到另一个页的指针。
在页处理期间,这个指针必须保持稳定。例如,在此期间不允许被另一个工作者线程(例如分页操作)将此指针无效。因此SQL Server在(单线程)索引查找操作期间,同时把持2个闩锁。下面这个图片很好的演示了这个重要概念。
当SQL Server在下层的页(页号257)上成功获取共享闩锁后,在索引根页(页号975)上的共享闩锁被释放。当SQL Server在中间层处理了这个页后,SQL Server在叶子层级的数据页(页号256)上获得共享闩锁,然后并在上层的页(页号257)上释放共享闩锁。当这个页成功处理后,最后在页号265上的共享闩锁也被释放。
小结
在这篇文章里我向你展示了在索引查找操作中,通过所谓的闩锁耦合概念,SQL Server如何获取和释放闩锁。一个常见的误解,在查找操作期间,SQL Server只在特定的页上获取闩锁。如你在今天的文章所见,这个并不真的正确。
感谢您的关注!
原文链接
http://www.sqlpassion.at/archive/2016/10/24/latch-coupling-in-sql-server/
SQL Server里的闩锁耦合(Latch Coupling)的更多相关文章
- SQL Server里的闩锁介绍
在今天的文章里我想谈下SQL Server使用的更高级的,轻量级的同步对象:闩锁(Latch).闩锁是SQL Server存储引擎使用轻量级同步对象,用来保护多线程访问内存内结构.文章的第1部分我会介 ...
- SQL Server里的自旋锁介绍
在上一篇文章里我讨论了SQL Server里的闩锁.在文章的最后我给你简单介绍了下自旋锁(Spinlock).基于那个基础,今天我会继续讨论SQL Server中的自旋锁,还有给你展示下如何对它们进行 ...
- 在SQL Server里为什么我们需要更新锁
今天我想讲解一个特别的问题,在我每次讲解SQL Server里的锁和阻塞(Locking & Blocking)都会碰到的问题:在SQL Server里,为什么我们需要更新锁?在我们讲解具体需 ...
- SQL Server里的文件和文件组
在今天的文章里,我想谈下SQL Server里非常重要的话题:SQL Server如何处理文件的文件组.当你用CREATE DATABASE命令创建一个简单的数据库时,SQL Server为你创建2个 ...
- sql server 里的文件和文件组使用
转自:https://www.cnblogs.com/woodytu/p/5821827.html 参考:https://www.sqlskills.com/blogs/paul/files-and- ...
- 在SQL Server里我们为什么需要意向锁(Intent Locks)?
在1年前,我写了篇在SQL Server里为什么我们需要更新锁.今天我想继续这个讨论,谈下SQL Server里的意向锁,还有为什么需要它们. SQL Server里的锁层级 当我讨论SQL Serv ...
- SQL Server里等待统计(Wait Statistics)介绍
在今天的文章里我想详细谈下SQL Server里的统计等待(Wait Statistics),还有她们如何帮助你立即为什么你的SQL Server当前很慢.一提到性能调优,对我来说统计等待是SQL S ...
- 在SQL Server里如何处理死锁
在今天的文章里,我想谈下SQL Server里如何处理死锁.当2个查询彼此等待时会发生死锁,没有一个查询可以继续它们的操作.首先我想给你大致讲下SQL Server如何处理死锁.最后我会展示下SQL ...
- SQL Server里如何处理死锁
在今天的文章里,我想谈下SQL Server里如何处理死锁.当2个查询彼此等待时会发生死锁,没有一个查询可以继续它们的操作.首先我想给你大致讲下SQL Server如何处理死锁.最后我会展示下SQL ...
随机推荐
- Java中有关Null的9件事
对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常 (NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我 ...
- Jquery 系列(1) 基本认识
本系列Jquery所用测试Demo版本是<uncompressed,development jQuery 1.11.3> 最新的jquery包可以从官网下载请参照http://jquery ...
- Async IO
I was recently reading a series on “Write Sequential Non-Blocking IO Code With Fibers in NodeJS” by ...
- 一步步学习javascript基础篇(1):基本概念
一.数据类型 数据类型 基本数据类型(五种) Undefined Null Boolean Number String 复杂数据类型(一种) Object Undefined:只有一个值undefin ...
- ABP理论学习之NHibernate集成
返回总目录 本篇目录 Nuget包 配置 实体映射 仓储 仓储基类 实现仓储 自定义仓储方法 阅读其他 ABP可以使用任何ORM框架工作,并且已经内置了NHibernate集成.这篇文章会解释如何在A ...
- addUser
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 再谈使用Emit把Datatable转换为对象集合(List<T>)
一.前因和存在的问题 前面我写了一篇<使用Emit把Datatable转换为对象集合(List<T>)>的博文,其实起源于我自己编写的一个orm工具(见前面几篇博文有介绍),里 ...
- 关闭form上chrome的autofill
Chrome的autofill会自动找到form中的type=password的元素,然后把这个元素前面的元素当做是用户名,它不在乎这个元素叫什么名字.这样又是注册又是登录,你会发现它自作聪明的aut ...
- 修改Credentials 密码
今天,Leader 吩咐要修改管理账户的密码,我负责的Part是修改package和 Replication的Job的密码.仔细想了下,由于我们使用的Windows验证方式,而Job在执行时,是使用P ...
- LINQ系列:LINQ to SQL Join连接
1. 一对多 var expr = context.Products .Where(p => p.Category.CategoryName == "LINQ to SQL" ...