fn_dblog()和fn_full_dblog()的使用
2023-01-03 20:08 abce 阅读(2142) 评论(0) 编辑 收藏 举报SQL Server 2017中,函数fn_full_dblog()对函数fn_dblog()做了改进,允许用户读取事务日志中的活跃部分,检索对数据库修改活动的相关信息。
使用fn_dblog()要记住以下几点:
1.只是返回事务日志中活跃部分的内容,比如打开的事务、或上一个活动
2.这是一个文档中没有列出的函数,官方有权修改且不用通知用户。因此不建议将其嵌入生产的代码中
函数的定义和查询
fn_dblog()必须在数据库上下文中调用,需要两个参数:开始和结束的日志序列号(LSN)。如果都设置为null,表示检索整个日志。
fn_db_log() SELECT * FROM fn_dblog ( NULL, -- Start LSN nvarchar(25) NULL -- End LSN nvarchar(25) )
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(如果成功提交的话),表示事务的开始和结束。
--查看活跃的事务 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表明操作的类型。整个列非常有用。以下是部分解释:
--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,一个数据页的大小。