Function Fn_PageResCracker Internals

In a previous blog post, I discussed two new methods to determine exactly which page a request might be waiting for when there is contention.  One of these new methods involves a new function, fn_pagerescracker.   Naturally, I wanted to see how this function operates.  Let’s look at the Master database to investigate how it works!

The function consumes a BINARY(8) parameter and returns a table.   This parameter represents a hexadecimal value that is constructed from the database ID, page ID, and file ID.

-------------------------------------------------------------------------------
-- Name: sys.fn_PageResCracker
--
-- Description:
--	Cracks the output of wait_resource page info
--
-- Notes:
-------------------------------------------------------------------------------
create function [sys].[fn_PageResCracker] (@physical_locator binary (8))
returns @dumploc_table table
(
	[db_id]	int not null,
	[file_id]	int not null,
	[page_id]	int not null
)
as
begin

	if @physical_locator is not null
	begin
		declare @db_id	binary (2)
		declare @file_id	binary (2)
		declare @page_id	binary (4)

		-- Page ID is the first four bytes, then 2 bytes of file ID, then 2 bytes of slot
		--
		select @page_id = convert (binary (4), reverse (substring (@physical_locator, 1, 4)))
		select @file_id = convert (binary (2), reverse (substring (@physical_locator, 5, 2)))
		select @db_id = convert (binary (2), reverse (substring (@physical_locator, 7, 2)))

		insert into @dumploc_table values (@db_id, @file_id, @page_id)
	end
	return
end
GO

You can see from the code that the parameter is then “diced” up with SUBSTRING commands and then converted into a small binary value.  Also, using SUBSTRING against a binary value (which is the parameter that is passed in) will return the number of bytes specified rather than the number of characters.  In this case, the Page ID is the first 4 bytes, the file ID is the following 2 bytes and finally the last 2 bytes represents the database ID.  Furthermore, when they are inserted into the table (which is returned to the calling query) it is then converted into an integer value.

Shown above, the page_resource value is 0x5001000001000600.  Now that we know how the function is going to work, we can do the math ourselves and confirm things.  Keep in mind that SQL Server utilizes big endians, so we will have to do some byte reversing.

Byte Breakdown
Page ID File ID Database ID
0x50010000 0x0100 0x0600

Page ID = 0x50010000, byte reversed is 0x00000150 (or 0x150), which when converted to an integer = 336

File ID = 0x0100, again byte reversed is 0x0001 (or 0x1), which when converted to an integer is 1.

Database ID = 0x0600, reversed once again, 0x0006 (or 0x6), which converted to an integer is 6.

We can see below that we have now confirmed that the function is working as expected!

Summary

One of things I enjoy the most is digging into the internals on how SQL Server works.  It continues to teach me new and exciting things.  It also helps to make me a better DBA in my opinion.  In this case, the value add isn’t super steep but it’s still fun tearing apart the logic.

Enjoy!

 

 

© 2019, John Morehouse. All rights reserved.

Share

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Trust DCAC with your data

Your data systems may be treading water today, but are they prepared for the next phase of your business growth?