转:使用fn_dblog解析SQL SERVER 数据库日志方法

http://blog.itpub.net/8183550/viewspace-682907

一直以来我都很困惑,不知道怎么解析SQL SERVER的日志,

因为微软提供了fn_dblog(NULL,NULL)和DBCC LOG获取数据库日志的基本信息,但是都是二进制码,看不懂。最近终于成功解析了SQL SERVER LOG信息

在fn_dblog(NULL,NULL)输出结果中,

获取表名是AllocUnitName字段。

具体获取方法:AllocUnitName like ‘dbo.TEST%‘

操作类型是:Operation

数据是:[RowLog Contents 0]字段内容

如果是UPDATE操作:修改后数据存放在[RowLog Contents 1]字段内

最基本3种操作类型:‘LOP_INSERT_ROWS‘,‘LOP_DELETE_ROWS‘,‘LOP_MODIFY_ROW‘

具体解析代码如下:

--解析日志
create function dbo.f_splitBinary(@s varbinary(8000))
returns @t table(id int identity(1,1),Value binary(1))
as
begin
declare @i int,@im int
select @i=1,@im=datalength(@s)
while @i<[email protected]
begin
  insert into @t select substring(@s,@i,1) 
  set @[email protected]+1
end
return
end

GO

create function dbo.f_reverseBinary(@s varbinary(128))
returns varbinary(128)
as
begin
declare @r varbinary(128)
set @r=0x
select @[email protected]+Value from dbo.f_splitBinary(@s) a order by id desc
return @r
end

GO
 
 
 
create proc [dbo].[p_getLog](@TableName sysname,@c int=100)
/*
解析日志
胡冰
时间:2010年12月30日
工作单位:www.5173.com

sample:  p_getLog ‘tablename‘;

*/
as
set nocount on
declare @s varbinary(8000),@s1 varbinary(8000),@str varchar(8000),@str1 varchar(8000),@lb int,@le int,@operation varchar(128)
declare @i int,@lib int,@lie int,@ib int,@ie int,@lenVar int,@columnname sysname,@length int,@columntype varchar(32),@prec int,@scale int
declare @TUVLength int,@vc int,@tc int,@bitAdd int,@bitCount int,@count int

select b.name,b.length,c.name typename,b.colid,b.xprec,b.xscale,
    case when c.name not like ‘%var%‘ and c.name not in (‘xml‘,‘text‘,‘image‘) then 1 else 2 end p,row_number() over(partition by 
    case when c.name not like ‘%var%‘ and c.name not in (‘xml‘,‘text‘,‘image‘) then 1 else 2 end order by colid) pid
into #t
    from sysobjects a inner join syscolumns b on a.id=b.id inner join systypes c on b.xtype=c.xusertype
    where [email protected] order by b.colid

SELECT top(@c) Operation,[RowLog Contents 0],[RowLog Contents 1],[RowLog Contents 2],[RowLog Contents 3],[Log Record],id=identity(int,1,1) into #t1
    from::fn_dblog (null, null) 
    where AllocUnitName like ‘dbo.‘[email protected]+‘%‘and
    Operation in(‘LOP_INSERT_ROWS‘,‘LOP_DELETE_ROWS‘,‘LOP_MODIFY_ROW‘ )
    AND Context not in (‘LCX_IAM‘,‘LCX_PFS‘)
     order by [Current LSN] desc

select @tc=count(*) from #t

select @lb=min(id),@le=max(id) from #t1
while @lb<[email protected]
begin
    select @operation=Operation,@s=[RowLog Contents 0],@s1=[RowLog Contents 1] from #t1 where [email protected] AND [RowLog Contents 1] IS NOT NULL
    set @TUVLength=convert(int,dbo.f_reverseBinary(substring(@s,3,2)))+3
    select @i=5,@str=‘‘,@vc=0,@bitCount=0
    select @lib=min(pid),@lie=max(pid) from #t where p=1 
    while @lib<[email protected]
    begin
        select @columnname=name,@length=length,@columntype=typename,@prec=xprec,@scale=xscale,@vc=colid-1 from #t where p=1 and [email protected]
--        if @columntype<>‘bit‘
--            print rtrim(@i)+‘->‘+rtrim(@length)

if dbo.f_reverseBinary(substring(@s,@TUVLength,1+((@tc-1)/8))) & power(2,@vc) <> 0 
        begin
            if @columntype<>‘bit‘
                select @[email protected][email protected]+‘=NULL,‘,@[email protected][email protected]
            else
            begin
                select @[email protected][email protected]+‘=NULL,‘
                set @bitAdd = case when @bitCount=0 then @i else @bitAdd end
                set @bitCount = (@bitCount + 1)%8    
                set @[email protected]+case @bitCount when 1 then 1 else 0 end
--                print rtrim(@bitAdd)+‘->‘+rtrim(@length)
            end                
        end
        else if @columntype=‘char‘
            select @[email protected][email protected]+‘=‘+convert(varchar(256),substring(@s,@i,@length))+‘,‘,@[email protected][email protected]gth
        else if @columntype=‘nchar‘
            select @[email protected][email protected]+‘=‘+convert(nvarchar(256),substring(@s,@i,@length))+‘,‘,@[email protected][email protected]
        else if @columntype=‘datetime‘
            select @[email protected][email protected]+‘=‘+convert(varchar,dateadd(second,convert(int,dbo.f_reverseBinary(substring(@s,@i,4)))/300
                ,dateadd(day,convert(int,dbo.f_reverseBinary(substring(@s,@i+4,4))),‘1900-01-01‘)),120)+‘,‘,@[email protected]+8
        else if @columntype=‘smalldatetime‘
            select @[email protected][email protected]+‘=‘+convert(varchar,dateadd(minute,convert(int,dbo.f_reverseBinary(substring(@s,@i,2)))
                ,dateadd(day,convert(int,dbo.f_reverseBinary(substring(@s,@i+2,2))),‘1900-01-01‘)),120)+‘,‘,@[email protected]+4
        else if @columntype=‘int‘
            select @[email protected][email protected]+‘=‘+rtrim(convert(int,dbo.f_reverseBinary(substring(@s,@i,4))))+‘,‘,@[email protected]+4
        else if @columntype=‘decimal‘
            select @[email protected][email protected]+‘=DECIMAL,‘,@[email protected][email protected]
        else if @columntype=‘bit‘
        begin
            set @bitAdd = case when @bitCount=0 then @i else @bitAdd end
            set @bitCount = (@bitCount + 1)%8
            select @[email protected][email protected]+‘=‘+rtrim(convert(bit,substring(@s,@bitAdd,1)&power(2,case @bitCount when 0 then 8 else @bitCount end-1)))+‘,‘
                ,@[email protected]+case @bitCount when 1 then 1 else 0 end
--            print rtrim(@bitAdd)+‘->‘+rtrim(@length)
        end
        set @[email protected]+1
    end
    set @i=convert(int,dbo.f_reverseBinary(substring(@s,3,2)))+4+((@tc-1)/8)
    set @lenVar=convert(int,dbo.f_reverseBinary(substring(@s,@i,2)))
    set @[email protected]+2
    set @[email protected] + @lenVar*2
    set @ie=convert(int,dbo.f_reverseBinary(substring(@s,@i,2)))
    set @count=0
    select @lib=min(pid),@lie=max(pid) from #t where p=2 
    while @lib<[email protected]
    begin
--        print rtrim(@ib)+‘->‘+rtrim(@ie)
        select @columnname=name,@length=length,@columntype=typename,@vc=colid-1 from #t where p=2 and [email protected]
        if dbo.f_reverseBinary(substring(@s,@TUVLength,1+((@tc-1)/8))) & power(2,@vc) <> 0 
        begin
            select @[email protected][email protected]+‘=NULL,‘
            select @[email protected]+1,@[email protected]+2
            if @count<@lenVar
                set @ie=convert(int,dbo.f_reverseBinary(substring(@s,@i,2)))
        end
        else if @columntype=‘varchar‘
        begin
            select @[email protected][email protected]+‘=‘+convert(varchar(256),substring(@s,@ib,@[email protected]+1))+‘,‘
            select @[email protected]+1,@[email protected]+2
            set @ie=convert(int,dbo.f_reverseBinary(substring(@s,@i,2)))
        end
        else if @columntype=‘nvarchar‘
        begin
            select @[email protected][email protected]+‘=‘+convert(nvarchar(256),substring(@s,@ib,@[email protected]+1))+‘,‘
            select @[email protected]+1,@[email protected]+2
            set @ie=convert(int,dbo.f_reverseBinary(substring(@s,@i,2)))
        end
        set @[email protected]+1
        set @[email protected]+1
    end
    set @str=left(@str,len(@str)-1)
    
     IF @operation =‘LOP_MODIFY_ROW‘  
     BEGIN
          set @TUVLength=convert(int,dbo.f_reverseBinary(substring(@s1,3,2)))+3
   select @i=5,@str1=‘‘,@vc=0,@bitCount=0
   select @lib=min(pid),@lie=max(pid) from #t where p=1 
   while @lib<[email protected]
   begin
    select @columnname=name,@length=length,@columntype=typename,@prec=xprec,@scale=xscale,@vc=colid-1 from #t where p=1 and [email protected]
  --        if @columntype<>‘bit‘
  --            print rtrim(@i)+‘->‘+rtrim(@length)

if dbo.f_reverseBinary(substring(@s1,@TUVLength,1+((@tc-1)/8))) & power(2,@vc) <> 0 
    begin
     if @columntype<>‘bit‘
      select @[email protected][email protected]+‘=NULL,‘,@[email protected][email protected]
     else
     begin
      select @[email protected][email protected]+‘=NULL,‘
      set @bitAdd = case when @bitCount=0 then @i else @bitAdd end
      set @bitCount = (@bitCount + 1)%8    
      set @[email protected]+case @bitCount when 1 then 1 else 0 end
  --                print rtrim(@bitAdd)+‘->‘+rtrim(@length)
     end                
    end
    else if @columntype=‘char‘
     select @[email protected][email protected]+‘=‘+convert(varchar(256),substring(@s1,@i,@length))+‘,‘,@[email protected][email protected]
    else if @columntype=‘nchar‘
     select @[email protected][email protected]+‘=‘+convert(nvarchar(256),substring(@s1,@i,@length))+‘,‘,@[email protected][email protected]
    else if @columntype=‘datetime‘
     select @[email protected][email protected]+‘=‘+convert(varchar,dateadd(second,convert(int,dbo.f_reverseBinary(substring(@s1,@i,4)))/300
      ,dateadd(day,convert(int,dbo.f_reverseBinary(substring(@s1,@i+4,4))),‘1900-01-01‘)),120)+‘,‘,@[email protected]+8
    else if @columntype=‘smalldatetime‘
     select @[email protected][email protected]+‘=‘+convert(varchar,dateadd(minute,convert(int,dbo.f_reverseBinary(substring(@s1,@i,2)))
      ,dateadd(day,convert(int,dbo.f_reverseBinary(substring(@s1,@i+2,2))),‘1900-01-01‘)),120)+‘,‘,@[email protected]+4
    else if @columntype=‘int‘
     select @[email protected][email protected]+‘=‘+rtrim(convert(int,dbo.f_reverseBinary(substring(@s1,@i,4))))+‘,‘,@[email protected]+4
    else if @columntype=‘decimal‘
     select @[email protected][email protected]+‘=DECIMAL,‘,@[email protected][email protected]
    else if @columntype=‘bit‘
    begin
     set @bitAdd = case when @bitCount=0 then @i else @bitAdd end
     set @bitCount = (@bitCount + 1)%8
     select @[email protected][email protected]+‘=‘+rtrim(convert(bit,substring(@s1,@bitAdd,1)&power(2,case @bitCount when 0 then 8 else @bitCount end-1)))+‘,‘
      ,@[email protected]+case @bitCount when 1 then 1 else 0 end
  --            print rtrim(@bitAdd)+‘->‘+rtrim(@length)
    end
    set @[email protected]+1
   end
   set @i=convert(int,dbo.f_reverseBinary(substring(@s1,3,2)))+4+((@tc-1)/8)
   set @lenVar=convert(int,dbo.f_reverseBinary(substring(@s1,@i,2)))
   set @[email protected]+2
   set @[email protected] + @lenVar*2
   set @ie=convert(int,dbo.f_reverseBinary(substring(@s1,@i,2)))
   set @count=0
   select @lib=min(pid),@lie=max(pid) from #t where p=2 
   while @lib<[email protected]
   begin
  --        print rtrim(@ib)+‘->‘+rtrim(@ie)
    select @columnname=name,@length=length,@columntype=typename,@vc=colid-1 from #t where p=2 and [email protected]
    if dbo.f_reverseBinary(substring(@s1,@TUVLength,1+((@tc-1)/8))) & power(2,@vc) <> 0 
    begin
     select @[email protected][email protected]+‘=NULL,‘
     select @[email protected]+1,@[email protected]+2
     if @count<@lenVar
      set @ie=convert(int,dbo.f_reverseBinary(substring(@s1,@i,2)))
    end
    else if @columntype=‘varchar‘
    begin
     select @[email protected][email protected]+‘=‘+convert(varchar(256),substring(@s1,@ib,@[email protected]+1))+‘,‘
     select @[email protected]+1,@[email protected]+2
     set @ie=convert(int,dbo.f_reverseBinary(substring(@s1,@i,2)))
    end
    else if @columntype=‘nvarchar‘
    begin
     select @[email protected][email protected]+‘=‘+convert(nvarchar(256),substring(@s1,@ib,@[email protected]+1))+‘,‘
     select @[email protected]+1,@[email protected]+2
     set @ie=convert(int,dbo.f_reverseBinary(substring(@s1,@i,2)))
    end
    set @[email protected]+1
    set @lib=[email protected]+1
   end
   set @str1=left(@str1,len(@str1)-1)

END
    
    IF @operation =‘LOP_MODIFY_ROW‘  
    BEGIN
     print   @operation+‘修改前值: ‘[email protected]
     
     print   @operation+‘修改后值:‘[email protected]
     
    END
    ELSE
 BEGIN
  print @operation+‘:‘[email protected]
 END
    
    
    
    
    set @[email protected]+1
END

drop table #t,#t1

GO

因为目前解析SQL 2008会有很多错误

时间: 2024-10-03 08:17:54

转:使用fn_dblog解析SQL SERVER 数据库日志方法的相关文章

收缩sql server数据库日志

项目中,可能数据库(sql server数据库)日志太多,占了很多磁盘空间,可以通过收缩数据库日志,减少日志文件大小. 下面以Northwind数据库为例: 1.把数据库的恢复模式设置为“简单模式”: 选择Northwind数据库-右键-属性, 在弹出的数据库属性窗口中,选择“选项”-设置恢复模式为“简单”, 点击确定按钮,如下图: 2.收缩数据库日志: 选择Northwind数据库-右键-任务-收缩-文件,如下图: 在弹出的“收缩文件”窗口里,文件类型选择“日志”,收缩操作勾选“释放未使用的空

查询SQL SERVER数据库日志工具

在SQL SERVER中查看操作日志,一直是一个比较麻烦的事情,因为微软并没有提供直接的系统工具可以查看日志内容,虽然可以通过非正式的隐藏接口dbcc log 获取日志的非解析编码但是要还原是个非常麻烦的事情.</DIV> <DIV>在SQL SERVER 2000到2005的时代可以通过LogExplor获取SQL SERVER 数据库内容,但是到了2008数据库后,发现LogExplor公司不再开发后续版本了,晚上在网上搜索了以下,发现一个非常好的工具ApexSQL Log.;

优化SQL Server数据库查询方法

SQL Server数据库查询速度慢的原因有很多,常见的有以下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6.查询出的数据量过大(可以采用多次查询,其他的方法降低数据量) 7.锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷) 8.sp_lock,sp_who,活动的用户查看,原因是读写竞争资源. 9.返回了不必要的行和列 10.查询语句不好,没有优

详解连接SQL Server数据库的方法,并使用Statement接口实现对数据库的增删改操作

总结一下,连接SQL Server数据库需要以下几个步骤: 1. 导入驱动Jar包:sqljdbc.jar 2. 加载并注册驱动程序 3. 设置连接路径 4. 加载并注册驱动 5. 连接数据库 6. 操作数据库 7. 关闭连接 代码如下: ******************连接数据库******************* 1 package zj6_Test; 2 import java.sql.*; 3 public class Zj6_3 { 4 /** 5 * 使用Statement接口

远程连接sql server 数据库的方法

今天找了半天,终于解决了如何从本地连接到远程sql server服务器的方法. 1.首先确保打开远程服务器的sql server配置管理器,确保TCP/IP协议开启 2.WebConfig的连接字符格式 <add name="SQLConnectionString" connectionString="Data Source=10.10.78.180,1433;Initial Catalog=db_Blog;User ID=sa;Password=123456;Pack

[SQL Server] 数据库日志文件自动增长导致连接超时的分析

1.现象.问题描述 客户反映某客户端登陆不了,客户端程序日志显示“连接数据库超时”:检查对应的数据库服务器,日志显示“Autogrow of file '某数据库日志文件' in database '某数据库' was cancelled by user or timed out after 2391 milliseconds.  Use ALTER DATABASE to set a smaller FILEGROWTH value for this file or to explicitly

SQL Server数据库日志清除

第一步 将数据库转换成 simple 模式 USE master GO ALTER DATABASE 所要删除日志的数据库名 SET RECOVERY SIMPLE WITH NO_WAIT GO 第二步 收缩数据库 USE 所要删除日志的数据库名 GO DBCC SHRINKDATABASE(N'所要删除日志的数据库名') GO 第三步 将数据库转换成原来的模式 USE master GO ALTER DATABASE 所要删除日志的数据库名 SET RECOVERY FULL WITH NO

让wampserver2.5.exe支持sql server数据库的方法

将D:\wamp\bin\php\php5.5.12\ext路径下 这两个文件复制到php.ini中 链接数据库方法 <?php $serverName = "."; $connectionInfo = array( "Database"=>"yunjianyan", "UID"=>"sa", "PWD"=>"123"); $conn = sq

SQL Server数据库备份方法

数据库备份,是在数据丢失的情况下,能及时恢复重要数据,防止数据丢失的一种重要手段.一个合理的数据库备份方案,应该能够在数据丢失时,有效地恢复重要数据,同时需要考虑技术实现难度和有效地利用资源. 数据库备份有四种类型,分别应用于不同的场合,下面简要介绍一下. 1.完全备份 这是大多数人常用的方式,它可以备份整个数据库,包含用户表.系统表.索引.视图和存储过程等所有数据库对象.但它需要花费更多的时间和空间,所以,一般推荐一周或一月做一次完全备份. 2.事务日志备份 事务日志是一个单独的文件,它记录数