,讲了SQLServer的自旋锁。当时以为自旋锁是对应OracleLATCH的一个结构体。事实上,碎片化阅读会带来一些不准确的知识。Oracle的LATCH通过自旋实现锁的获取,自旋是LATCH获取轻量级锁的一种方式。在SQLServer中,LATCH和自旋锁被设计成两种轻量级的锁,分别用于不同的场景。Oracle有sharedpool、librarycache等结构,sharedpoollatches可以用来保护整个sharedpool。sharedpool中一些新加入的杂乱数据结构可以通过sharedpoollatch和mutex序列化。SQLServer中没有这种机制,所以LATCH是为了保护一些访问量大的内存结构而设计的,而自旋锁则用于其他一些数据结构。在SQLSERVER中,自旋锁总是用于保护访问速度非常快的内存结构。LATCH是SQLServer的SQL引擎使用的一种轻量级原子操作,用于确保内存结构的一致性,以保护索引、数据页和内部结构,例如B树中的非叶页。LATCH只存在于SQL引擎内部。SQLServer使用bufferLATCH来保护缓冲池中的页面,使用I/OLATCH来保护尚未加载到缓冲池中的页面。每当向SQLServer缓冲池中的页面写入数据或从中读取数据时,工作线程必须首先为该页面获取缓冲的LATCH。有几种缓冲区LATCH类型可用于访问缓冲池中的页面,包括独占LATCH(PAGELATCH_EX)和共享LATCH(PAGELATCH_SH)。当SQLServer访问一个还没有加载到缓冲池中的页面时,它会通过异步I/O操作将页面加载到缓冲池中。如果SQLServer需要等待I/O子系统响应,它会根据请求类型等待独占(PAGEIOLATCH_EX)或共享(PAGEIOLATCH_SH)I/OLATCH;这样做是为了防止另一个工作线程将具有不兼容LATCH的同一页加载到缓冲池中。LATCH还用于保护对缓冲池页面以外的内部内存结构的访问;这些被称为无缓冲锁存器。PAGELATCH争用在多CPU系统中很常见。当多个线程同时尝试获取同一内存结构的不兼容LATCH时,就会发生LATCH争用。闩锁是一种内部并发控制机制,SQL引擎会自动确定何时使用它们。因为锁存器的行为是确定性的,所以数据库模式的设计、表、索引等的设计都会影响锁存器的争用。非缓存页的闩锁名称为LATCH_XX,其中“_XX”后缀表示闩锁的模式(PAGEIOLATCH/PAGELATCH也使用后缀表示模式)。SQLServer的latch模式可以概括为:lKP-KeepLATCH,保证被引用的结构不被破坏。当线程想要查看缓冲区结构时使用。由于KPLATCH兼容除Destroy(DT)之外的所有LATCH,因此KPLatch被认为是“轻量级的”,这意味着它在使用时对性能的影响最小。由于KP锁存器与DT锁存器不兼容,它可以防止任何其他线程破坏引用的结构。KPlatch会防止它引用的结构被lazywriter进程破坏(脏块写入磁盘,释放buffer);lSH--sharedlatch,需要读取引用的结构(如读取数据页)。多个线程可以并发访问共享闩锁下的资源以进行读取。lUP-更新锁存器,与SH(共享锁存器)和KP兼容,但与其他锁存器不兼容,因此不允许EX锁存器写入引用结构。lEX-防止其他线程写入或读取引用结构的独占锁存器。一个使用示例是修改页面内容以防止页面损坏。lDT-销毁锁存器,必须在销毁引用结构的内容之前获取。例如,lazywriter进程必须获取一个DT锁存器以释放一个干净的页面,然后再将它添加到其他线程可用的空闲缓冲区列表中。上面描述中latch兼容性的描述可以用上表表示。如果我们看到一个锁存器,我们可以通过“_”后的后缀来区分它的模式。例如,PAGEIOLATCH_EX是一个独占的PAGEIOLATCH,而LATCH_DT是一个非缓冲区保护的销毁锁存器。类似于Oracle的sub-latch,SQLSERVER也有类似的结构,称为superlatch或sublatch。目的是使用多个childlatch来提高latch的并发性能。SQLSERVER采用多线程结构,采用动态缓冲区扩展的方法。因此对superlatch机制和NUMA架构进行了优化,更好的适配NUMA。SuperLatches可以提高访问共享页面的性能,其中多个并发运行的工作线程需要SH锁存器。为此,SQLServer引擎将此类页面上的锁存器动态提升为SuperLatch。在为大型服务器设计的高吞吐量系统上,高并发latch争用是必然发生的,在这样的系统中是很正常的。但是,当闩锁争用和闩锁等待类型的等待时间足够长以降低CPU利用率时,系统的整体吞吐量会严重下降。识别和识别闩锁争用的迹象很重要,所以让我们有能力分析情况。SQLServer闩锁的预期行为(与每秒事务数有关)是每秒事务数将随着平均SQLServer闩锁等待时间的增加而增加,而它本身的增加速度很慢。如果数据库并发增长的趋势与闩锁等待的趋势非常接近,那么闩锁争用就不会产生额外的负面影响。如果latch等待的时间远远超过数据库负载的增加,则latch上存在严重的争用。这个判断原则在大多数情况下是有效的。好久没仔细看数据库厂商的官方白皮书了。通过这两天的学习,我学会了一种分析数据的方法。事实上,一些指标之间存在着相对同步的关系。通过增加或减少的比较(可以通过统计方法计算出一个可评估的度量),可以发现一些系统性能问题。以前我们做了一个指标相关性分析工具,用来发现数据库中某个指标异常可能存在的问题。事实上,通过这种更简单的算法,也可以发现系统中一些偏离预期行为的场景,并用于告警。
