代码改变世界

fn_dblog()和fn_full_dblog()的使用

  abce  阅读(2383)  评论(0编辑  收藏  举报

SQL Server 2017中,函数fn_full_dblog()对函数fn_dblog()做了改进,允许用户读取事务日志中的活跃部分,检索对数据库修改活动的相关信息。

使用fn_dblog()要记住以下几点:

1.只是返回事务日志中活跃部分的内容,比如打开的事务、或上一个活动

2.这是一个文档中没有列出的函数,官方有权修改且不用通知用户。因此不建议将其嵌入生产的代码中

 

函数的定义和查询

fn_dblog()必须在数据库上下文中调用,需要两个参数:开始和结束的日志序列号(LSN)。如果都设置为null,表示检索整个日志。​

1
2
3
4
5
fn_db_log()
SELECT * FROM fn_dblog (
              NULL, -- Start LSN nvarchar(25)
              NULL  -- End LSN nvarchar(25)
       )

  

1
2
3
4
5
6
7
8
9
10
11
12
fn_full_dblog()
SELECT * FROM sys.fn_full_dblog
 (
  NULL, -- Start LSN nvarchar (25)
  NULL, -- End LSN nvarchar (25) 
  NULL, -- Database ID int
  NULL, -- Page file ID int
  NULL, -- Page ID int
  NULL, -- Logical Database ID nvarchar (260)
  NULL, -- Backup Account nvarchar (260)
  NULL -- Backup Container nvarchar (260)
 )

如果你想传入指定的LSN,需要转换LSN的格式,将3个16进制的数字转换成varchar。

 

返回的列

fn_dblog()和fn_full_dblog()返回相同的列,共有130个列,以下是我测试中比较有用的列:

SID、XACTID和SPID只是出现在事务的开头或结尾。每个事务都有LOP_BEGIN_XACT和LOP_COMMIT_XACT(如果成功提交的话),表示事务的开始和结束。​

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
--查看活跃的事务
SELECT * FROM sys.dm_tran_active_transactions;
SELECT * FROM sys.dm_tran_database_transactions;
DBCC OPENTRAN();
-- Get Log usage for a specific transaction
SELECT *
FROM fn_dblog(NULL,NULL)
WHERE [Transaction ID] IN (SELECT [Transaction ID] FROM fn_dblog(null,null) WHERE [Transaction SID] = 0x6163d86d97bd6a4da016bac4330f975f)
  
-- Get Log usage for a specific SPID
SELECT *
FROM fn_dblog(NULL,NULL)
WHERE [Transaction ID] IN (SELECT [Transaction ID] FROM fn_dblog(null,null) WHERE [SPID] = 78)
  
-- Get Log usage for a specific user specified transaction
SELECT *
FROM fn_dblog(NULL,NULL)
WHERE [Transaction ID] IN (SELECT [Transaction ID] FROM fn_dblog(null,null) WHERE [Xact ID] = 277094)
  
-- Get the active part of the LOG for a specific transaction
SELECT
       [Current LSN]
       ,[Previous LSN]
       ,[Operation]
       ,[Context]
       ,[Transaction ID]
       ,[Log Record Length]
       ,[AllocUnitName]
       ,[Page ID]
       ,[SPID]
       ,[Xact ID]
       ,[Begin Time]
       ,[End Time]
       ,[Transaction Name]
       ,[Transaction SID]
       ,[Parent Transaction ID]
       ,[Transaction Begin]
       ,[Number of Locks]
       ,[Lock Information]
       ,[Description]
       ,[Log Record]
FROM sys.fn_dblog(null,null)
WHERE [Transaction ID] = '0000:00011043'
 

Operations列

Operations表明操作的类型。整个列非常有用。以下是部分解释:

1
2
3
4
5
6
7
--See all operations and their size
SELECT
[Operation],count(*) AS [No of Records],
SUM([Log Record Length]/1024.00/1024.00) AS [RecordSize (MB)]
FROM fn_dblog(NULL,NULL)
GROUP BY Operation
ORDER BY [RecordSize (MB)] DESC

 

使用场景

使用fn_dblog()分析'SELECT … INTO'和'INSERT … SELECT'语句的差异。

从图中可以看到,借助使用fn_dblog(),比'INSERT … SELECT'语句比'SELECT … INTO'语句更昂贵,因为它是逐行插入。

第一个图中,LOP_INSERTED_ROWS结果是776317,使用100MB的日志;第二个图中,可以看到是逐行插入且都记入了日志。

另一方面,'SELECT … INTO'只是将页dump到新的表。LOP_FORMAT_PAGE是最昂贵的操作(41MB);但是看第二个图中每条日志记录的长度,是8KB,一个数据页的大小。

 

相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示