Buffer Latch Timeout的解析

  【问题描述】

  我们可能会在数据库的错误日志里,发现这么一条信息:

A time-out occurred while waiting for buffer latch -- type 4, bp 000000097BFDEDC0, page 1:19239, stat 0xc00009, database id: 5, allocation unit Id: 72057615247867904, task 0x0000000005E594C8 : 0, waittime 300, flags 0x1018, owning task 0x0000000000169DC8. Not continuing to wait. 

  我们的问题是,这个错误到底是什么含义,在什么情况下会报上面的错误,以及如何解决?

  【背景介绍】

  Latch是SQL Server内部用来同步资源访问的一个数据结构。和操作系统的Critical Section或ReaderWriterLock类似。Latch保护了那些想保护的资源,使得访问同步有序。比方说,当某个线程获得某个资源的Latch的独占使用权时候,别的线程如果也需要访问这个Latch,则它必须等待。

  从大的方面来讲,有两种Latch,一种叫Buffer Latch,另外一种叫I/O Latch。

  我们先来简短介绍一下I/O Latch。当SQL Server从硬盘上读取一个页时,会先在内存预留该页的空间。并且在该预留空间的某一个位BUF_IO设为1。如果数据从硬盘读写完成,则该位设为0。从硬盘读取页的期间,其他也需要访问该页的线程当然要等待,等待类型为PAGEIOLATCH_SH,直到读写完成,BUF_IO被设为0为止。因此,如果我们看到大量PAGEIOLATCH_SH等待,则基本可以断定问题是出在磁盘性能上面。

  另外一种Latch则称为Buffer Latch,用来保护内存里的数据结构,如Index, Data Pages, B树中的Non-Leaf页。当进程需要读取一个内存里的数据页时,该进程要先获取该数据页上的Buffer Latch。有各种类型的Latch,包括独占Latch(PAGELATCH_EX)和共享Latch(PAGELATCH_SH)。

  下面来演示,为什么我们需要Latch。如下图所示,我们在页面100上,已经存放了两条记录。

  如果没有Latch锁的话,某进程在页面100上,插入如下数据:INSERT VALUES(3, 300),其结果如下:

  这时,另外一个进程要在页面100上,插入如下数据: INSERT VALUES(4, 400), 因为没有Latch锁,所以会覆盖之前的数据。导致数据插入出问题。

  正确的做法是,我们要在第一个线程进行操作时,加独占Latch锁。第二个线程必须要等待,直到第一个线程操作完成。如下图所示:

  开始第一条记录插入,随后修改m_freedata(值为141)以及Row的指针(值为126),在此期间,第二条插入语句处于等待Latch状态。第一条记录插入完成后,释放独占Latch锁。

  第二条记录开始插入,插入期间也会加独占Latch锁,以防止其他进程修改或读取页。完成后,也随即释放Latch锁。最后结果如图所示。由于有Latch锁,所以数据的插入可以有序的进行。

  【LATCH申请模式】

  Latch在申请的时候有以下几种模式,

  • KP – Keep Latch 保证引用的结构不能被破坏
  • SH – Shared Latch 读数据页的时候需要
  • UP – Update Latch 更改数据页的时候需要
  • EX – Exclusive Latch 独占模式,主要用于写数据页的时候需要
  • DT – Destroy Latch 在破坏引用的数据结构时所需要

  下表显示各种Latch申请的兼容模式:

 

  Y表明是兼容的,如果两个线程都去读某页,则他们都会去申请SH锁,因为SH锁是兼容的,则两个线程都不会互相妨碍。而N表明是不兼容的,必须要等待。直到前面一个Latch被释放为止。

  【LATCH等待类型】

  Latch的等待主要有三种。

  1. Buffer (BUF) Latch 用来保护索引或数据页,也包括PFS, GAM, SGAM和IAM数据页,等待类型是PAGELATCH_*模式。
  2. Non-buffer (Non-BUF) Latch 除了上述数据结构以外的其他内存结构,等待类型是LATCH_*模式。
  3. IO Latch 保护数据从磁盘到页面的读写过程,等待类型是PAGEIOLATCH_*模式。

  我们可以查询下面的语句了解一下具体的等待种类:

SELECT * FROM sys.dm_os_wait_stats WHERE wait_type like '%Latch%'

it知识库Buffer Latch Timeout的解析,转载需保留来源!

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。