Jun 032015 Posted in Corruption, Scripts0 Responses

Convert LSN to Numeric

As part of the Database Corruption Challenge I needed to convert the LSN values returned by fn_dblog() / fn_dump_dblog() to numeric.

The math is not very simple and it is best described by Paul Randal.

  • Take the rightmost 4 characters (2-byte log record number) and convert to a 5-character decimal number, including leading zeroes, to get stringA
  • Take the middle number (4-byte log block number) and convert to a 10-character decimal number, including leading zeroes, to get stringB
  • Take the leftmost number (4-byte VLF sequence number) and convert to a decimal number, with no leading zeroes, to get stringC
  • The LSN string we need is stringC + stringB + stringA

You may download the script that will create the function from here, or use the code below to build your own:

RAISERROR('Create function: [dbo].[ufn_convertLSNToNumeric]', 10, 1) WITH NOWAIT
GO
IF  EXISTS (SELECT * FROM sysobjects WHERE id = OBJECT_ID(N'[dbo].[ufn_convertLSNToNumeric]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[ufn_convertLSNToNumeric]
GO

CREATE FUNCTION [dbo].[ufn_convertLSNToNumeric]
(		
	@LSN		[varchar](22)
)
RETURNS [numeric](25)
/* WITH ENCRYPTION */
AS

-- ============================================================================
-- Author	 : Dan Andrei STEFAN
-- Create date	 : 26.05.2015
-- Module	 : Database Analysis & Performance Monitoring
-- ============================================================================

/*
	
		
		
	Take the rightmost 4 characters (2-byte log record number) and convert to a 5-character decimal number, including leading zeroes, to get stringA
	Take the middle number (4-byte log block number) and convert to a 10-character decimal number, including leading zeroes, to get stringB
	Take the leftmost number (4-byte VLF sequence number) and convert to a decimal number, with no leading zeroes, to get stringC
	The LSN string we need is stringC + stringB + stringA

	00000001:00000001:0001
*/
begin
	RETURN	CAST(CAST(CAST(CAST(CONVERT(VARBINARY, '0x' + RIGHT(REPLICATE('0', 8) + LEFT(@LSN, 8), 8), 1) As int)  AS VARCHAR(32)) as varchar(8)) + 
			CAST(RIGHT(REPLICATE('0', 10) + CAST(CAST(CONVERT(VARBINARY, '0x' + RIGHT(REPLICATE('0', 8) + SUBSTRING(@LSN, 10, 8), 8), 1) As int)  AS VARCHAR(32)), 10) as varchar(10)) + 
			CAST(RIGHT(REPLICATE('0', 5) + CAST(CAST(CONVERT(VARBINARY, '0x' + RIGHT(REPLICATE('0', 8) + RIGHT(@LSN, 4), 8), 1) As int)  AS VARCHAR(32)), 5) as varchar(5)) AS [numeric](25))
end

GO

Leave a Reply

Your email address will not be published. Please enter your name, email and a comment.

*