SQL Server Latches(闩锁)
Posted 薛定谔的DBA
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL Server Latches(闩锁)相关的知识,希望对你有一定的参考价值。
SQL Server 闩锁是一种特殊类型的低级别系统锁。在 SQL Server 中,内部闩锁体系结构在 SQL 操作期间保护内存。它确保内存结构与页面读写操作一致性。
SQL Server 闩锁是一种内部的 SQL Server 机制,用于保护共享内存资源,比如缓冲池中的页面和内存数据结构,以便协调对这些资源的访问并保护它们免受破坏。闩锁不会暴露在 SQL Server 操作系统(SQLOS)之外,闩锁只能由SQL Server 自己管理,而不能由用户管理(与可以通过 NOLOCK 提示管理的锁不同)。每当 SQL Server 读取内存时,它都会对无法以适当多线程方式访问的页面或内部内存结构施加闩锁。这样SQL Server就创建了闩锁,为 SQL Server 数据库中多个物理线程协调执行的资源。与我们常用的锁一样,闩锁也有不同的模式。
闩锁模式
Destroy Latch (DT): 最严格的闩锁模式,当一个闩锁被销毁并从缓存中移除一个缓冲区时获得。DT闩锁甚至堵塞KP闩锁。
Exclusive Latch (EX): 获得正在写入的页面的独占控制权。防止在EX闩锁所在页上获取所有其他闩锁。
Update Latch (UP): 类似于排他闩锁的限制性闩锁,但它允许读操作访问页面,但显式地限制任何写操作。
Keep Latch (KP): 用于保存闩锁顺序记录,但也确保它在放置新闩锁时留在缓冲区中。
Shared Latch (SH): 当向页面发出读取请求被授予时在页面上的闩锁。
与锁类似,各种闩锁模式之间也存在兼容性或不兼容性。下表提供了对各种 SQL Server 闩锁器之间兼容性的深入了解
有许多不同类型的 SQL Server 闩锁,但基本上它们可以分为三大类:I/O 闩锁、缓冲区闩锁和非缓冲区闩锁。
I/O 闩锁(I/O latches)
当在缓冲池中存储的页面上执行未完成的 I/O 操作时,或更准确地说,当数据读取或写入到物理存储时,将获取 I/O 闩锁。当 SQL Server 出现等待 I/O 闩锁被释放的时候,SQL Server 将使用 PAGEIOLATCH_XX 等待类型来报告该进程。
因此,当请求将页面从存储写入到缓冲时,在该页面上则获取 PAGEIOLATCH。如果存储未准备好读取,则 PAGEIOLATCH 等待类型计数将增加。
缓冲区闩锁(Buffer latches)
为了正确理解缓冲区闩锁,理解内存缓冲池背后的思想很重要,它是围绕最大化 SQL Server 性能的目标而设计的。缓冲池是一个物理内存范围,从磁盘读取的数据存储在内存数据页中。SQL Server 表中的数据以页为单位存储的,每个页的大小固定为 8192 字节 (8 KB)。每当必须读取或写入数据页时,它将数据放入缓冲池。这样,对该页的任何进一步访问都将直接从内存缓冲池中读取,从而减少磁盘 IO 来提高 SQL Server 性能。
SQL Server 中内存池概念可以是导致物理内存使用率高的原因,即使没有 SQL Server 活动的情况下也是一样。缓冲池中的数据加载基于先进先出 (FIFO) 原则。
SQL Server 使用缓冲区管理器来管理缓冲池。SQLOS 正在通过缓冲区管理器专门访问存储在内存中的数据。(可通过DMV查询 sys.dm_os_memory_clerks)
由于执行DML命令而在缓冲池中修改的页面称为“脏”页面,而未修改的页面称为“干净”页面。因此,当在内存中访问页面时,SQLOS 将获取该页面上的缓冲区闩锁。与锁不同的是,SQL Server 闩锁不会在事务持续期间被持有,而是在事务的关键时期被持有,一旦不再需要它就会被释放。当 SQL Server 出现等待缓冲区闩锁被释放的时候,SQL Server 将使用 PAGELATCH_XX 等待类型来报告该进程。
非缓冲区闩锁(Non-buffer latches)
非缓冲闩锁旨在保护和保证缓冲池中存储的页面以外的任何物理内存结构。当 SQL Server 出现等待缓冲区闩锁被释放的时候,SQL Server 将使用 LATCH_XX 等待类型来报告该进程。在此期间不经常遇到非缓冲区闩锁,因此这些是最少记录的,但是这里有一些用非缓冲闩锁可能导致SQL Server竞争的示例:
-
过多的并行。在具有 12 个逻辑处理器以上的服务器中使用高度并行的情况下,大多数查询都可以使用并行执行计划。在这种情况下,将在内存中获取非缓冲闩锁(LATCH_XX)以确保并行执行计划使用的内部内存结构的同步。
-
过多的自动增长/自动收缩操作。在数据库大小或存储容量规划不佳的系统中,自动增长操作频繁执行。另外,当开启自动收缩时,会出现频繁的数据库收缩。在执行增长和收缩操作时,SQL Server 获取 FCB、FGCB_ADD_REMOVE 和 FGCB_ALLOC 这类闩锁,以确保对文件控制块的访问,并确保对存储在文件组中的信息同步访问。
-
堆和 BLOB 数据结构上的频繁运行 DML 操作。在对堆和 BLOB 数据执行过多 DML 操作的情况下,有必要确保所有内部内存结构负责分配和释放页面同步到堆。在这种情况下,可能会遇到过多的 LATCH_EX 等待类型。在这种情况下,通过 sys.dm_os_latch_stats 可以找到 ALLOC_CREATE_FREESPACE_CACHE、ALLOC_FREESPACE_CACHE、ALLOC_EXTENT_CACHE 等待类型。
因此,当 LATCH_XX 等待类型出现过多值,最好使用以下查询检查 SQL Server 中普遍存在哪些非缓冲区闩锁
SELECT latch_class, wait_time_ms,waiting_requests_count
, 100.0 * wait_time_ms / SUM (wait_time_ms) OVER() AS '% of latches'
FROM sys.dm_os_latch_stats
WHERE latch_class NOT IN ('BUFFER')
AND wait_time_ms > 0
闩锁争用对于拥有大量 CPU 的系统来说是一种常见的情况,它在相同的内存结构上,多个线程同时尝试获取彼此不兼容的 SQL Server 闩锁的结果。由于 SQL Server 闩锁是由 SQL Server 内部机制控制的,所以 SQLOS 将自己决定何时使用它们。
在为大量 CPU 的设计的高吞吐量系统,由于经常使用闩锁访问和保护内存结构,因此预计会出现高并发、活动闩锁争用。但是当闩锁争用和闩锁等待类型等待时间大到足以降低 CPU 利用率时,将会导致吞吐量降低。因此,识别和识别闩锁争用的迹象是很重要的。
以上是关于SQL Server Latches(闩锁)的主要内容,如果未能解决你的问题,请参考以下文章