基于sys.fn_dblog()的SQL Server日志分析

本文介绍如何在SQL Server环境中使用自定义工具MSSQLLogAnalyzer分析数据库日志,并通过示例演示如何进行在线恢复操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Github URL: https://github.com/ap0405140/MSSQLLogAnalyzer 

在SQL Server 2005及之前的版本, 可以用Log Explorer工具来分析读取数据库日志, 但据我所知, SQL2008及之后的版本, Log Explorer工具暂时无法支持.

 因此,我们可以自己开发工具来实现分析读取数据库日志的目的,大致思路如下: 

  1.使用系统函数sys.fn_dblog()读取原始日志信息.

  2.通过系统表sys.tables,sys.columns,sys.systypes等获取表结构及数据类型.

  3.分析数据库日志,得到日志中每步操作对应的正向SQL(Redo)和反向SQL(Undo).

详细的实验步骤如下:

1.建测试表dbo.OrderDetail.

create table dbo.OrderDetail
(OrderID int not null,
 ItemID int not null,
 ItemNumber varchar(10),
 QTY int,
 Price decimal(8,2),
 ADate date,
 AUser char(20),
 UDate datetime,
 UUser varchar(20)
 constraint pk_OrderDetail primary key(OrderID,ItemID)
)

2. 操作1: 新增3行

-- 操作1: 新增3行
insert into dbo.OrderDetail(OrderID,ItemID,ItemNumber,QTY,Price,ADate,AUser,UDate,UUser)
  select 1001,1,'D001',100,45.62,'2015-01-02','Xh6','2015-01-03 20:15:18','Lx4'  union all
  select 1001,2,'Z001_2',150,180,'2015-01-02','cx5','2015-01-08 02:45:32','Yx3' union all
  select 1002,1,'Z001_2',300,182.07,'2015-12-12','CL1','2015-12-18 02:45:32','LY6'
 
select * from dbo.OrderDetail

结果如下:

3. 操作2: 更新1行

-- 操作2: 更新1行
update dbo.OrderDetail set QTY=999 where OrderID=1001 and ItemID=1

select * from dbo.OrderDetail

结果如下:

4.操作3: 更新3行

-- 操作3: 更新3行
update dbo.OrderDetail set ItemNumber='!@#$%'

select * from dbo.OrderDetail

结果如下:

5. 操作4: 删除3行

-- 操作4: 删除3行
delete from dbo.OrderDetail

select * from dbo.OrderDetail


结果如下:

此时, 目标表已为空, 接下来, 我们通过MSSQLLogAnalyzer.exe工具来实现在线恢复.

 

恢复步骤如下:

下载或克隆demo程序包到本地, Github URL: https://github.com/ap0405140/MSSQLLogAnalyzer 

1. 执行MSSQLLogAnalyzer.exe, 

1.1 修改数据库连接串(ConnectionString)参数为实际环境值, 连接目标数据库.

1.2 修改需解析日志的时间范围, 即开始时间(StartTime)和结束时间(EndTime).

1.3 表名(TableName)可以为空, 代表将解析所有表的日志.

1.4 点击[Readlog]按钮, 等待解析结果.

执行结果:

从上图可以看到, 返回了正向SQL(RedoSQL)和反向SQL(UndoSQL), 

2.复制出所有反向SQL(UndoSQL)的值.  因结果默认是按时间升序排列, 恢复时需注意按时间降序排列执行反向SQL(UndoSQL), 即自下往上.

3.恢复各个操作, 执行反向SQL(UndoSQL).

-- 恢复原操作4(删除3行) 
insert into dbo.OrderDetail([OrderID],[ItemID],[ItemNumber],[QTY],[Price],[ADate],[AUser],[UDate],[UUser]) values(1002, 1, '!@#$%', 300, 182.07, '2015-12-12', 'CL1', '2015-12-18 02:45:32.000', 'LY6'); 
insert into dbo.OrderDetail([OrderID],[ItemID],[ItemNumber],[QTY],[Price],[ADate],[AUser],[UDate],[UUser]) values(1001, 2, '!@#$%', 150, 180.00, '2015-01-02', 'cx5', '2015-01-08 02:45:32.000', 'Yx3'); 
insert into dbo.OrderDetail([OrderID],[ItemID],[ItemNumber],[QTY],[Price],[ADate],[AUser],[UDate],[UUser]) values(1001, 1, '!@#$%', 999, 45.62, '2015-01-02', 'Xh6', '2015-01-03 20:15:18.000', 'Lx4'); 

-- 恢复原操作3(更新3行)
update dbo.OrderDetail set [ItemNumber]='Z001_2' where [OrderID]=1002 and [ItemID]=1
update dbo.OrderDetail set [ItemNumber]='Z001_2' where [OrderID]=1001 and [ItemID]=2
update dbo.OrderDetail set [ItemNumber]='D001' where [OrderID]=1001 and [ItemID]=1

-- 恢复原操作2(更新1行)
update dbo.OrderDetail set [QTY]=100 where [OrderID]=1001 and [ItemID]=1

查看恢复结果, 

select * from dbo.OrderDetail

结果如下, 即回到原操作1之后的结果, 恢复完成!

 

<think>嗯,用户想在SQL Server中查询数据库修改的历史记录,也就是数据库的修改日志。这个问题需要我仔细分析。首先,我应该回忆一下SQL Server的日志机制和相关工具。 我记得SQL Server的事务日志记录了所有数据库的修改操作,包括插入、更新、删除等,用于恢复和事务完整性。但直接查询事务日志可能比较复杂,因为日志是二进制格式的。不过,用户可能需要的是类似于审计日志的功能,查看谁在什么时候做了什么修改。 根据用户提供的引用,引用[2]提到了使用xp_readerrorlog来读取SQL Server的错误日志,但错误日志主要是记录服务器事件,可能不包括具体的数据库修改操作。不过用户的问题是关于数据库修改的历史记录,这可能涉及到事务日志或变更数据捕获(CDC)等功能。 另外,引用[4]中提到了清理日志的方法,但用户需要的是查询日志,而不是清理。所以可能需要其他方法。比如,SQL Server提供了fn_dblog函数来读取事务日志,但这是未公开的函数,使用时需谨慎。此外,还有SQL Server Audit功能,可以配置审计策略来跟踪特定的操作。 可能还需要考虑是否启用了CDC或变更跟踪(Change Tracking),这些功能可以记录数据的变化。如果用户没有启用这些功能,那么可能需要依赖事务日志的分析,但这比较复杂。 总结一下,可能的解决方案包括: 1. 使用fn_dblog函数直接查询事务日志,但需要解析二进制数据。 2. 配置SQL Server Audit来记录所需的修改操作。 3. 使用CDC或变更跟踪功能,如果已经启用的话。 4. 查看默认的跟踪文件,如果默认跟踪尚未被覆盖的话。 需要逐步引导用户,先确认是否有启用审计或CDC,如果没有,可能需要建议他们配置。同时,提醒他们直接解析事务日志的复杂性和风险,可能推荐使用官方支持的审计方法更为稳妥。</think>在 SQL Server 中查询数据库修改日志,可通过以下步骤实现: ### 一、通过事务日志读取(需谨慎操作) 1. **使用未公开函数 `fn_dblog`** ```sql SELECT [Operation], [Begin Time], [Transaction Name], [Transaction SID] FROM fn_dblog(NULL, NULL) WHERE Operation IN ('LOP_INSERT_ROWS','LOP_MODIFY_ROW','LOP_DELETE_ROWS') ``` *此方法可查看基本操作类型和时间,但数据以二进制格式存储,需结合系统表解析具体内容*[^2][^3]。 2. **解析日志详细信息**(需关联系统表) ```sql SELECT l.[Transaction ID], t.[Begin Time], t.[Transaction Name], s.name AS SchemaName, o.name AS TableName FROM fn_dblog(NULL, NULL) l JOIN sys.dm_tran_database_transactions t ON t.transaction_id = l.[Transaction ID] JOIN sys.objects o ON o.object_id = l.[AllocUnitId] JOIN sys.schemas s ON s.schema_id = o.schema_id ``` ### 二、使用 SQL Server Audit 功能(推荐方案) 1. **创建审计规范** ```sql USE master; CREATE SERVER AUDIT DBAudit TO FILE (FILEPATH = 'D:\Audit\'); ALTER SERVER AUDIT DBAudit WITH (STATE = ON); CREATE DATABASE AUDIT SPECIFICATION SchemaChanges FOR SERVER AUDIT DBAudit ADD (SCHEMA_OBJECT_CHANGE_GROUP), ADD (DATABASE_OBJECT_CHANGE_GROUP) WITH (STATE = ON); ``` *此配置会记录所有架构和数据库对象变更*[^1][^4]。 2. **查询审计日志** ```sql SELECT event_time, action_id, succeeded, session_id, database_name, object_name FROM sys.fn_get_audit_file('D:\Audit\*', NULL, NULL) WHERE action_id IN ('DRDL','SL','UP','DL','IN') ``` ### 三、通过默认跟踪文件(仅保留最近日志) ```sql SELECT StartTime, EventClass, ObjectName, LoginName, TextData FROM sys.fn_trace_gettable( (SELECT value FROM sys.fn_trace_getinfo(1) WHERE property = 2), DEFAULT ) WHERE EventClass IN (46,47,164) -- 对象创建/删除/修改事件 ``` ### 四、补充说明 - **日志保留策略**:事务日志默认会循环覆盖,需定期备份或启用审计功能长期保存 - **权限要求**:需要 `CONTROL SERVER` 权限访问审计日志 - **性能影响**:审计功能会增加约5%-10%的I/O负载,需评估服务器性能[^1][^4]
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值