侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

简单介绍SQL Server里的闩锁

数据库  /  管理员 发布于 5年前   214

在今天的文章里我想谈下SQL Server使用的更高级的,轻量级的同步对象:闩锁(Latch)。闩锁是SQL Server存储引擎使用轻量级同步对象,用来保护多线程访问内存内结构。文章的第1部分我会介绍SQL Server里为什么需要闩锁,在第2部分我会给你介绍各个闩锁类型,还有你如何能对它们进行故障排除。

为什么我们需要闩锁?
闩锁首次在SQL Server 7.0里引入,同时微软首次引入了行级别锁(row-level locking)。对于行级别锁引入闩锁的概念是非常重要的,不然的话在内存中会出现丢失更新(Lost Updates)的现象。如我所说的,闩锁是存储引擎使用的轻量级同步对象,是SQL Server用来保护内存结构的。闩锁只不过是类似于多线程编程里的所谓的临界区(Critcal Section)概念。

在传统并发编程里,临界区是同时只能一个线程运行的代码。闩锁本身是个临界区的特殊版本,因为它允许多个并发读操作。在SQL Server的上下文里这意味着多个线程可以并发读取一个共享数据结构,例如内存中的页,但是写入共享数据结构必须是单个线程进行。

闩锁是用来协调数据库里多个线程物理执行,然而锁是基于选择的事务隔离级别,用来逻辑获得需要的隔离级别。作为开发者或DBA的你,你可以用不同方式影响锁――例如通过SQL Server里的隔离级别,或者通过各种可用锁提示。另一方面闩锁是不能以直接方式控制的。在SQL Server里没有闩锁提示,也没有可用闩锁隔离级别。下表是锁和闩锁之间的比较:

                 锁(Locks)         闩锁(Latches)

控制……             事务              线程
保护……              数据库内容          内存中数据结构
模式……             共享的(Shared),      保持(Keep),
                 更新(Update),         共享的(Shared),

                 排它的(Exclusive),     更新(Update),排它的(Exclusive),

                 意向的(Intension)      销毁(Destroy)

死锁……           检测并解决(detection&resolution)  通过严谨代码来避免
保持在……  锁管理器的哈希表(Hashtable)   保护的数据结构(Protected Data Structure)
从表里可以看到,闩锁支持更细粒度保持(Keep)和销毁(Destroy)模式。保持闩锁主要用来引用计数,例如当你想知道在指定闩锁上有多少其它闩锁在等待。销毁闩锁是最有限制的一个(它甚至会阻塞保持闩锁),当闩锁被销毁时会用到,例如当惰性写入器(Lazy Writer)想要释放内存中的页时。我们先介绍下各种闩锁模式,然后说下各个闩锁模式的兼容性。

NL(空闩锁):

                   内部
                   未使用

KP(保持闩锁):

                   可以由多个任务同时持有
                   只被一个DT模式的闩锁阻塞

SH(共享闩锁):

                  读取数据页的时候使用
                   可以由多个任务同事持有
                  阻塞EX模式和DT模式的闩锁

UP(更新闩锁):

                  写入系统分配页面和tempdb的行版本化页面时使用
                 一个这种模式的闩锁只能被一个单独的任务持有

EX(排它闩锁):

                   写入数据页的时候使用
                   一个这种模式的闩锁只能被一个单独的任务持有

DT(销毁闩锁):

                  很少使用
                  一个这种模式的闩锁只能被一个单独的任务持有

在SQL Server里,一致性不能只用锁来获得。SQL Server还是可以访问没被锁管理器保护的共享数据结构,例如页头。还有SQL Server基于闩锁基础的其他组件也是,有单线程代码路径。好了,我们继续讲解SQL Server里的各种闩锁类型,还有如何对它们进行故障排除。

闩锁类型与故障排除
SQL Server区分3个不同闩锁类别

                   IO闩锁
                 缓冲区闩锁(BUF)
                 非缓冲区闩锁(Non-BUF)

我们来详细看下这3个不同类别。当在缓冲池的页读写操作未完成――即当你读自/写入你的存储子系统时(2者未同步),SQL Server会使用IO闩锁(I/O Latches)。对于这些I/O闩锁,SQL Server在统计信息里以PAGEIOLATCH_为前缀出现。你可以在DMV sys.dm_os_wait_stats 查看下这些闩锁类型的等待。

复制代码 代码如下:SELECT * FROM sys.dm_os_wait_stats WHERE wait_type LIKE 'PAGEIOLATCH_%'

使用这些闩锁,SQL Server保证那些页不会并发多次读入缓存池,那些页也不会从缓存池忽略,在那些页需要被查询访问的时候。

除这些I/O闩锁外,SQL Server也支持所谓的缓存区闩锁(Buffer Latches),它用来保护缓冲池里页不会被并发运行的线程影响。这些闩锁,SQL Server使用它们来阻止内存中的丢失更新(Lost Updates)。没有这类闩锁,在缓存池里会有并发的读写页,它们会引发主内存里页的损坏。对于这些缓存闩锁,SQL Server在统计信息里以PAGELATCH_为前缀出现。你可以在DMV sys.dm_os_wait_stats 查看下这些闩锁类型的等待。这里最重要的是你涉及了主内存的竞争,因为他们的等待类型名称里不包含IO字样。

复制代码 代码如下: SELECT * FROM sys.dm_os_wait_stats WHERE wait_type LIKE 'PAGELATCH_%'

最后SQL Server内部使用所谓的非缓存区闩锁(Non-Buffer Latches)来保护除缓冲池外的共享数据结构。对于这些非缓存闩锁,SQL Server在统计信息里以LATCH_为前缀出现。你可以在DMV sys.dm_os_wait_stats 查看下这些闩锁类型的等待。

复制代码 代码如下: SELECT * FROM sys.dm_os_wait_stats WHERE wait_type LIKE 'LATCH_%'

但在这个DMV里这些对于非缓存区闩锁的等待只是SQL Server内部使用的各个闩锁的概况信息,你可以在单独的DMV sys.dm_os_latch_stats找到更详细的信息。

复制代码 代码如下: SELECT * FROM sys.dm_os_latch_stats

SQL Server 2014内部使用163个闩锁来同步共享数据结构的访问。其中一个著名的闩锁是FGCB_ADD_REMOVE,它用来保护文件组的文件组控制阻塞( File Group Control Block (FGCB)),在以下特定操作期间:

        文件增长(手动或自动)
       增加/删除文件组文件
       重新计算填充比重(Recalculating proportional fill weightings)
       在循环分配期间,通过文件组的文件回收。
当你看到这个闩锁排在前列是,你肯定有太多自动增长操作的问题,原因是你数据库糟糕的默认配置。当查询尝试读/写保护的数据结构且需要等待一个闩锁时,查询就会进入挂起状态,直到闩锁可以成功获取。因此查询经过的整个查询生命周期包括运行(RUNNING),挂起(SUSPENDED),可运行(RUNNABLE),最后再次运行(RUNNING)。因此,当查询长时间把持闩锁时,强制共享数据结构保护才有意义。那是因为改变查询状态也意味着进行Windows系统里的上下文切换,依据引入的CPU周期是个很昂贵的操作。

因此对于读写频繁或极短时间内的共享数据结构上放上闩锁没有意义。在这个情况下,需要的上下文切换会杀死SQL Server的整体性能,它需要花费太多的时间来完成整个查询生命周期(运行(RUNNING),挂起(SUSPENDED),可运行(RUNNABLE))。那就是是SQL Server引入的所谓自旋锁(Spinlocks)。锁管理器就是这样数据结构的好例子:当锁定或解锁数据对象(例如记录,页等)时只需要单个线程访问。但当你查看sys.dm_os_latch_stats时,你会发现没有闩锁保护锁管理器本身。锁管理器使用的哈希表里对应的哈希桶使用自旋锁来保护――LOCK_HASH自旋锁。通过锁管理器执行锁定和解锁操作前,必须获得自旋锁。

以上就是本文的全部内容,希望大家可以喜欢。


  • 上一条:
    为什么我们需要在SQL Server里更新锁
    下一条:
    简单介绍SQL Server中的自旋锁
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 分库分表的目的、优缺点及具体实现方式介绍(0个评论)
    • DevDB - 在 VS 代码中直接访问数据库(0个评论)
    • 在ubuntu系统中实现mysql数据存储目录迁移流程步骤(0个评论)
    • 在mysql中使用存储过程批量新增测试数据流程步骤(0个评论)
    • php+mysql数据库批量根据条件快速更新、连表更新sql实现(0个评论)
    • 近期文章
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-06
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-01
    • 2018-05
    • 2018-10
    • 2018-11
    • 2020-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2021-02
    • 2021-04
    • 2021-07
    • 2021-08
    • 2021-11
    • 2021-12
    • 2022-02
    • 2022-03
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客