In a multithreaded process what would happens when a one thread updates a data or index page in memory while second thread is reading the same page?
What will happen when 1st thread reads a data/index page in memory while 2nd thread is freeing the same page from memory?
Answer: We would end up with data or data structure inconsistency. To avoid inconsistency SQL Server uses Synchronization Mechanisms like Locks,Latches and Spinlocks.
We will discuss few key points about latches and how to debug latch timeout dumps in this blog.
What is Latch ?
They control the concurrent access to data pages and structures by multiple threads. Latches provide physical data consistency of data pages and provide synchronization for data structures. Latches are not controllable by user like locks.
Types of the Latch:
Buffer (BUF) Latch
Used to synchronize access to BUF structures and their associated database pages.
Buffer “IO” Latch
A subset of BUF latches used when the BUF and associated data/index page is in the middle of an IO operation (Reading page from disk or writing page to disk).
Non-Buffer (Non-BUF) Latch
These are latches that are used to synchronize general in-memory data structures generally used by queries/tasks executed by parallel threads, auto grow operations , shrink operations etc.
Keep (KP) Latches
Used to ensure that the page is not released from memory while it is in use.
Shared (SH) Latches
Used for read-only access to data structures and prevent write access by others threads.
This mode allows shared access.
SH is compatible with KP, SH, and UP. It should be noted that although in general SH implies read-only access, it is not always the case. For buffer latches SH is the minimum mode required in order to read a data page.
Update (UP) Latches
Allows read access to the data structure(Compatible with SH and KP), but prevents other EX-latch access.
Used for write operations when torn page detection is off and when AWE is not enabled.
Exclusive (EX) Latches
Prevents any read activity from occurring on the latched structure. EX is only compatible with KP.
Used during read IO during write IO when torn page detection is on or AWE is enabled.
Destroy (DT) Latches
Used when removing BUFs from the buffer pool, either by adding them to the free list or unmapping AWE buffers.
How do you identify Latch contention?
Latch contention can be identified using below wait types in sysprocesses.
PAGEIOLATCH_*: This waittype in sysprocesses indicates that SQL Server is waiting on a physical I/O of a buffer pool page to complete.
1. PAGEIOLATCH_* are commonly solved by tuning the queries which are performing heavy IO (Commonly by adding, changing and removing indexes (or) statistics to reduce the amount of physical IO).
2. Identifying if there is disk bottleneck and fixing them (Pageiolatch wait times (ex > 30 ms))
PAGELATCH_*: This waittype in sysprocesses indicates that SQL Server is waiting on access to a database page, but the page is not undergoing physical IO.
1. This problem is normally caused by a large number of sessions attempting to access the same physical page at the same time. We should Look at the wait resource of the spid. The wait_resource is the page number (the format is dbid:file:pageno)
that is being accessed.
2. We can use DBCC PAGE to identify object or type of the page in which we have the contention. Also it will help us to determine whether contention is for allocation, data or text.
3. If the pages that SQL Server is most frequently waiting on are in tempdb database ,check the wait resource column for a page number in dbid 2. You may be facing tempdb allocation latch contention mentioned in http://support.microsoft.com/kb/328551
4. If the page is in a user database, check to see if the table has a clustered index on a monotonic key such as an identity where all threads are contending for the same page at the end of the table. In this case we need to choose a different
clustered index key to spread the work across different pages.
LATCH_*: Non-buf latch waits can be caused by variety of things. We can use the wait resource column in sysprocesses to determine the type of latch involved(KB 822101).
1. A very common LATCH_EX wait is due to running a profiler trace or sp_trace_getdata Refer KB 929728 for more information.
2. Auto Grow and auto shrink.
When a latch is requested by thread and If that latch cannot be granted immediately because of some other thread holding a incompatible latch on same page or data structure then the requestor must wait for the latch to be grantable. Warning messages like one below is printed in SQL Server error log and a mini dump with all the threads is captures if the wait interval reaches 5 minutes (waittime 300). The warning message differs for buffer and non-buffer latches.
844: Time out occurred while waiting for buffer latch — type %d, bp %p, page %d:%d, stat %#x, database id: %d, allocation unit id: %I64d%ls, task 0x%p : %d, waittime %d, flags 0x%I64x, owning task 0x%p. Continuing to wait.
846: A time-out occurred while waiting for buffer latch — type %d, bp %p, page %d:%d, stat %#x, database id: %d, allocation unit Id: %I64d%ls, task 0x%p : %d, waittime %d, flags 0x%I64x, owning task 0x%p. Not continuing to wait.
847: Timeout occurred while waiting for latch: class ‘%ls’, id %p, type %d, Task 0x%p : %d, waittime %d, flags 0x%I64x, owning task 0x%p. Continuing to wait.
Break up of above warning
The latch mode of the current latch acquire request. This is a numerical value with the following mapping: 0 – NL (not used); 1 – KP; 2 – SH; 3 – UP; 4 – EX; 5 – DT.
Task for which we are trying to acquire latch.
The total time waited for this latch acquire request in seconds.
The address of the Task that owns the latch, if available.
bp (Buffer latches only)
The address of the BUF structure corresponding to this buffer latch.
page (Buffer latches only.)
The page id for the page currently contained in the BUF structure.
database id (Buffer latches only.)
The database id for the page in the BUF.
Like troubleshooting blocking issues in SQL Server when there is a latch contention or timeout dump identify the owner of latch and troubleshoot why the latch is held by the owner for long time.
When there is latch timeout dump you will see a warning message similar to one below. Warning error message printed in SQL server errorlog before the dump is very important to find the owner thread of latch.
2012-01-18 00:52:03.16 spid69 A time-out occurred while waiting for buffer latch — type 4, bp 00000000ECFDAA00, page 1:6088, stat 0x4c1010f, database id: 4, allocation unit Id: 72057594043367424, task 0x0000000006E096D8 : 0, waittime 300, flags 0x19,
owning task 0x0000000006E08328. Not continuing to wait.
spid21s **Dump thread – spid = 21, PSS = 0x0000000094622B60, EC = 0x0000000094622B70
spid21s ***Stack Dump being sent to E:\Data\Disk1\MSSQL.1\MSSQL\LOG\SQLDump0009.txt
spid21s * *******************************************************************************
spid21s * BEGIN STACK DUMP:
spid21s * 02/28/12 00:32:03 spid 21
spid21s * Latch timeout
Timeout occurred while waiting for latch: class ‘ACCESS_METHODS_HOBT_COUNT’, id 00000002D8C32E70, type 2, Task 0x00000000008FCBC8 : 7, waittime 300, flags 0x1a, owning task 0x00000000050E1288. Continuing to wait.
Timeout occurred while waiting for latch: class ‘ACCESS_METHODS_HOBT_VIRTUAL_ROOT’, id 00000002D8C32E70, type 2, Task 0x00000000008FCBC8 : 7, waittime 300, flags 0x1a, owning task 0x00000000050E1288. Continuing to wait.
From the error message above we can easily understand we are trying to acquire latch on database id: 4, page 1:6088 (6088 page of first file) and we timed out because task 0x0000000006E08328 (owning task 0x0000000006E08328 in warning message) is holding a latch on it.
Note: Task is simply a work request to be performed by the thread. (such as system tasks, login task, Ghost cleanup task etc.). Threads which execute the task will take required latches on need.
Let us see how to analyze latch timeout dump and get the owning thread of the Latch using the owning task 0x0000000006E08328.
To analyze the dump download and Install Windows Debugger from This link
Open Windbg . Choose File menu –> select Open crash dump –>Select the Dump file (SQLDump000#.mdmp)
on command window type
Type .reload /f and hit enter. This will force debugger to immediately load all the symbols.
Verify if symbols are loaded for SQL Server by using the debugger command lmvm
0:002> lmvm sqlservr
start end module name
00000000`01000000 00000000`03679000 sqlservr T (pdb symbols) c:\websymbols\sqlservr.pdb\21E4AC6E96294A529C9D99826B5A7C032\sqlservr.pdb
Loaded symbol image file: sqlservr.exe
Image path: C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn\sqlservr.exe
Image name: sqlservr.exe
Timestamp: Wed Oct 07 21:15:52 2009 (4ACD6778)
File version: 2005.90.4266.0
Product version: 9.0.4266.0
File flags: 0 (Mask 3F)
File OS: 40000 NT Base
File type: 1.0 App
File date: 00000000.00000000
Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4
Use the below command to search thread stack to identify the thread which has reference to the owning task and it will be the thread which is owning the latch. Replace 0X0000000006E08328 with owning task in your errorlog
~*e .echo ThreadId:; ?? @$tid; r? @$t1 = ((ntdll!_NT_TIB *)@$teb)->StackLimit; r? @$t2 = ((ntdll!_NT_TIB *)@$teb)->StackBase; s -d @$t1 @$t2 0X0000000006E08328
unsigned int 0x93c
unsigned int 0x9a0
unsigned int 0x9b4
00000000`091fdaf0 06e08328 00000000 00000000 00000000 (……………
00000000`091fdcb8 06e08328 00000000 091fdd70 00000000 (…….p…….
00000000`091fded0 06e08328 00000000 06e0e798 00000000 (……………
00000000`091fdf38 06e08328 00000000 00000002 00000000 (……………
00000000`091fec60 06e08328 00000000 0168883a 00000000 (…….:.h…..
00000000`091ff260 06e08328 00000000 000007d0 00000000 (……………
00000000`091ff2d0 06e08328 00000000 00000020 00000000 (……. …….
00000000`091ff5f8 06e08328 00000000 800306c0 00000000 (……………
00000000`091ff6c0 06e08328 00000000 00000000 00000000 (……………
00000000`091ff930 06e08328 00000000 00000000 00000001 (……………
00000000`091ff9b8 06e08328 00000000 00000000 00000000 (……………
00000000`091ffa38 06e08328 00000000 00000000 00000000 (……………
00000000`091ffc10 06e08328 00000000 03684080 00000000 (……..@h…..
00000000`091ffc90 06e08328 00000000 00000000 00000000 (……………
unsigned int 0x9b8
unsigned int 0x9bc
unsigned int 0x9c0
From the above out put we see thread 0x9b4 has reference to the pointer of owning task and it will be the thread which is owning the latch. Let us switch to the thread(0x9b4 ) which is executing the owning task and
then go through the stack to see why the thread is owning the latch for long time.
~~[0x9b4]s ==> Switching to the thread (Replace 0x9b4 with your thread id which has reference to the po
00000000`77ef047a c3 ret
0:002> kC ==> Print the stack
From the above stack we can understand that the thread which is owning the latch is executing checkpoint and flushing cache (Dirty buffers) to disk. If flushing buffers to disk (checkpoint) is taking a long time, then obviously there is disk bottleneck.
Similarly for any other latch time out issues first identify the owner thread of latch, read the stack of owner thread to understand the task performed by owner thread and troubleshoot the performance of task performed by owner thread.
If you want to see the stack of thread which is waiting, then pickup the task (task 0x0000000006E096D8 )from latch timeout warning message in errorlog instead of owning task (task 0x0000000006E08328) and use the command mentioned in step 5.
I hope this post will help you to learn and debug the latch timeout issues.
If you liked this post, do like us on Facebook at https://www.facebook.com/mssqlwiki and join our Facebook group https://www.facebook.com/mssqlwiki#!/groups/454762937884205/