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

来源:互联网 发布:dmpdp文件导入数据库 编辑:程序博客网 时间:2024/05/16 09:28

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

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

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

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

  3.调用SQL CLR(C#实现) 分析数据库日志,得到日志中每步操作对应的正向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=1select * 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.OrderDetailselect * from dbo.OrderDetail

结果如下:




此时, 目标表已为空, 接下来, 我们通过系统函数sys.fn_dblog()和调用SQL CLR来实现在线恢复.

恢复步骤如下:

1. 分析查询日志, 得到反向操作SQL序列.

exec dbo.DBA_ReadDatabaseLog @startTime='2016-01-14 00:00:00',  -- 开始时间                             @endTime='2016-01-31 23:59:59',    -- 结束时间                             @objectName='dbo.OrderDetail',    -- 表名                             @sorttype='DESC'                  -- 日志排序方式(升序/降序)

执行结果:




得到正向SQL(Redo)和反向SQL(Undo), 

2.复制出所有反向SQL, 即结果中的UndoSQL列.   因结果是按时间倒序排列, 因此顺序刚好与之前的操作顺序相反, 便于恢复操作.

3.恢复各个操作.

-- 恢复原操作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]=1update dbo.OrderDetail set [ItemNumber]='Z001_2' where [OrderID]=1001 and [ItemID]=2update 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之后的结果, 恢复完成!



3 0
原创粉丝点击