0
点赞
收藏
分享

微信扫一扫

SQLSERVER 事务日志的 LSN 到底是什么?

一:背景

1. 讲故事

大家都知道​​数据库应用程序​​​ 它天生需要围绕着数据文件打转,诸如包含数据的 ​​.mdf​​​,事务日志的 ​​.ldf​​​,很多时候深入了解这两类文件的合成原理,差不多对数据库就能理解一半了,关于 ​​.mdf​​​ 的合成前面的文章已经有所介绍,这篇我们来聊一下 ​​.ldf​​​ 的一些内部知识,比如 ​​LSN​​。

二:对 LSN 的理解

1. 什么是 LSN

如果大家玩过 SQLSERVER 的发布订阅或者 AlwaysOn 或多或少都见过 ​​LSN​​​,比如下面的格式: ​​00000030:00018090:0002​​​ ,这一串编号到底是什么意思呢?本质上指示的是 ​​.ldf​​ 文件的某一个物理位置上的偏移,画个图大概如下:

SQLSERVER 事务日志的 LSN 到底是什么?_数据库

从图中可以看到其实是由 ​​虚拟文件号:日志段起始扇区编号:槽号编号​​​ 三部分组成,要了解这三部分就需要明白 ​​.ldf​​ 文件是如何进行逻辑划分的,画个简图如下:

SQLSERVER 事务日志的 LSN 到底是什么?_槽号_02

通过上面的图很容易就能明白其中的逻辑关系,事务日志文件被划分成了多个 ​​虚拟文件​​​,虚拟文件又划分成了多个 ​​日志段​​​,日志段又划分成了多个 ​​扇区​​​,日志段中日志记录位置存储在 ​​槽号​​ 中,有了这些理论基础,接下来用一个案例来加深大家的理解吧。

2. 一个案例演示

新建一个 ​​MyLSN​​​ 数据库,再创建一个 ​​test​​ 表,插入 3w 条记录,sql如下:

CREATE DATABASE MyLSN
GO
USE MyLSN
GO
CREATE TABLE test(a INT IDENTITY, b CHAR(10) DEFAULT 'aaaaaaaaaa')

SET NOCOUNT ON
INSERT INTO test (b) DEFAULT VALUES
GO 30000
SET NOCOUNT OFF

接下来通过 ​​fn_dblog​​​ 来查询和 ​​dbo.test​​ 表相关的事务日志记录。

SELECT [Current LSN],
Operation,
Context,
AllocUnitName,
[RowLog Contents 0],
[Log Record],
[Log Record Length]
FROM fn_dblog(NULL, NULL)
WHERE AllocUnitName LIKE '%test%';

SQLSERVER 事务日志的 LSN 到底是什么?_槽号_03

从图中可以看到这是一个 ​​INSERT​​​ 的事务日志记录,这里就拿编号 ​​00000030:00000db0:0002​​ 去定位 .ldf 中的物理偏移位置吧,要想获取物理偏移就要知道下面偏移值才可以。

  1. 0x30 虚拟文件号的偏移值是多少 ?

要想知道这个信息,可以用 ​​DBCC loginfo​​​ 命令,查看 ​​FSeqNo​​​下的 ​​StartOffset​​​ 偏移值即可,即 0n48 对应的 ​​4071424​​ ,截图如下:

SQLSERVER 事务日志的 LSN 到底是什么?_数据库_04

  1. 0xdb0 扇区号的偏移是多少?

大家都知道磁盘的扇区是 512byte,sqlserver 为了更好的写入磁盘,也用了 512byte 这个粒度,所以偏移值就是 ​​512 * 0xdb0​​。

综合上面就能定位到日志段的物理偏移值为:

lkd> ?0n4071424 + (0n3504*0n512)
Evaluate expression: 5865472 = 00000000`00598000

接下来用 ​​WinHex​​​ 来定位 ​​MyLSN_log.ldf​​​ 文件偏移 ​​00598000​​ 的位置,定位之前先将数据库离线。

ALTER DATABASE MyLSN SET OFFLINE

SQLSERVER 事务日志的 LSN 到底是什么?_日志记录_05

前面的 ​​0x0003​​​ 表示该日志段只有 3 条记录,后面的 ​​0x019E​​​ 表示该日志段的大小为 ​​414byte​​,接下来就是槽号了,槽号位置的物理偏移计算规则如下:

lkd> ? 00598000 + 019E - 1
Evaluate expression: 5865885 = 00000000`0059819d

SQLSERVER 事务日志的 LSN 到底是什么?_槽号_06

从图中可以看到,slot2 的偏移值为 ​​00C8​​​,即物理偏移值为 ​​005980c8​​ 。

lkd> ? 00598000 + 00C8
Evaluate expression: 5865672 = 00000000`005980c8

SQLSERVER 事务日志的 LSN 到底是什么?_数据库_07

从上面框出的内容可以轻松的看到,事务日志中记录了 Insert 的 ​​aaaaaaaaaa​​​ 值,太棒了,起始就是 ​​fn_dblog​​​ 查出来的 ​​Log Record​​ 值。

SQLSERVER 事务日志的 LSN 到底是什么?_日志记录_08

三:总结

对 LSN 有一个深度的理解,对各种数据库事务日志暴涨的故障分析都会有一个很好的理论基础,后面我们再聊这些话题。



举报

相关推荐

0 条评论