Tiger Software Supreme mistakenly deletes historical data. Clears product information. Member stored-value card information. DELETE UPDATE DROP TABLE recovery solution.

[Case cleanup]

Today, I received a call from a customer and reported that I have used Tiger Extreme Software for many years.

Due to the slow speed of the software card, I want to reduce the size of the database by cleaning up historical data.

Improve database performance, so care.

Inadvertently mishandled, deleted all the basic information such as the classification of the product information supplier and the stored value of the membership card.

【problem analysis】

In such special circumstances, you need to stop the SQL service historically, and copy the  physical files of D:\Program Files\Microsoft SQL Server\MSSQL\Data
MDF and LDF database for backup.

 

Stop all writing and updating operations to the database, and don't make the situation worse and cause new error coverage.

 

[Solution experience]

1. Of course, the first thing is to back up the data in time, and you can play it whatever you want.

2. Obtain basic information of database logs through fn_dblog(NULL, NULL) and DBCC LOG provided by Microsoft,

But they are all binary codes, so I don't understand them. Recently successfully parsed SQL SERVER LOG information 

In the output result of fn_dblog(NULL,NULL),

Get the table name is the AllocUnitName field.

Specific method of obtaining: AllocUnitName like'dbo.TEST%'

The operation type is: Operation

The data is: [RowLog Contents 0] field content

If it is an UPDATE operation: the modified data is stored in the [RowLog Contents 1] field

The most basic 3 types of operations:'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<=@im
begin
  insert into @t select substring(@s,@i,1) 
  set @i=@i+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 @r=@r+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)
/*
解析日志

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 a.name=@TableName 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.'+@TableName+'%'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<=@le
begin
    select @operation=Operation,@s=[RowLog Contents 0],@s1=[RowLog Contents 1] from #t1 where id=@lb 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<=@lie
    begin
        select @columnname=name,@length=length,@columntype=typename,@prec=xprec,@scale=xscale,@vc=colid-1 from #t where p=1 and pid=@lib
--        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 @str=@str+@columnname+'=NULL,',@i=@i+@length
            else
            begin
                select @str=@str+@columnname+'=NULL,'
                set @bitAdd = case when @bitCount=0 then @i else @bitAdd end
                set @bitCount = (@bitCount + 1)%8    
                set @i=@i+case @bitCount when 1 then 1 else 0 end
--                print rtrim(@bitAdd)+'->'+rtrim(@length)
            end                
        end
        else if @columntype='char'
            select @str=@str+@columnname+'='+convert(varchar(256),substring(@s,@i,@length))+',',@i=@i+@length
        else if @columntype='nchar'
            select @str=@str+@columnname+'='+convert(nvarchar(256),substring(@s,@i,@length))+',',@i=@i+@length
        else if @columntype='datetime'
            select @str=@str+@columnname+'='+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)+',',@i=@i+8
        else if @columntype='smalldatetime'
            select @str=@str+@columnname+'='+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)+',',@i=@i+4
        else if @columntype='int'
            select @str=@str+@columnname+'='+rtrim(convert(int,dbo.f_reverseBinary(substring(@s,@i,4))))+',',@i=@i+4
        else if @columntype='decimal'
            select @str=@str+@columnname+'=DECIMAL,',@i=@i+@length
        else if @columntype='bit'
        begin
            set @bitAdd = case when @bitCount=0 then @i else @bitAdd end
            set @bitCount = (@bitCount + 1)%8
            select @str=@str+@columnname+'='+rtrim(convert(bit,substring(@s,@bitAdd,1)&power(2,case @bitCount when 0 then 8 else @bitCount end-1)))+','
                ,@i=@i+case @bitCount when 1 then 1 else 0 end
--            print rtrim(@bitAdd)+'->'+rtrim(@length)
        end
        set @lib=@lib+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 @i=@i+2
    set @ib=@i + @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<=@lie
    begin
--        print rtrim(@ib)+'->'+rtrim(@ie)
        select @columnname=name,@length=length,@columntype=typename,@vc=colid-1 from #t where p=2 and pid=@lib
        if dbo.f_reverseBinary(substring(@s,@TUVLength,1+((@tc-1)/8))) & power(2,@vc) <> 0 
        begin
            select @str=@str+@columnname+'=NULL,'
            select @ib=@ie+1,@i=@i+2
            if @count<@lenVar
                set @ie=convert(int,dbo.f_reverseBinary(substring(@s,@i,2)))
        end
        else if @columntype='varchar'
        begin
            select @str=@str+@columnname+'='+convert(varchar(256),substring(@s,@ib,@ie-@ib+1))+','
            select @ib=@ie+1,@i=@i+2
            set @ie=convert(int,dbo.f_reverseBinary(substring(@s,@i,2)))
        end
        else if @columntype='nvarchar'
        begin
            select @str=@str+@columnname+'='+convert(nvarchar(256),substring(@s,@ib,@ie-@ib+1))+','
            select @ib=@ie+1,@i=@i+2
            set @ie=convert(int,dbo.f_reverseBinary(substring(@s,@i,2)))
        end
        set @count=@count+1
        set @lib=@lib+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<=@lie
   begin
    select @columnname=name,@length=length,@columntype=typename,@prec=xprec,@scale=xscale,@vc=colid-1 from #t where p=1 and pid=@lib
  --        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 @str1=@str1+@columnname+'=NULL,',@i=@i+@length
     else
     begin
      select @str1=@str1+@columnname+'=NULL,'
      set @bitAdd = case when @bitCount=0 then @i else @bitAdd end
      set @bitCount = (@bitCount + 1)%8    
      set @i=@i+case @bitCount when 1 then 1 else 0 end
  --                print rtrim(@bitAdd)+'->'+rtrim(@length)
     end                
    end
    else if @columntype='char'
     select @str1=@str1+@columnname+'='+convert(varchar(256),substring(@s1,@i,@length))+',',@i=@i+@length
    else if @columntype='nchar'
     select @str1=@str1+@columnname+'='+convert(nvarchar(256),substring(@s1,@i,@length))+',',@i=@i+@length
    else if @columntype='datetime'
     select @str1=@str1+@columnname+'='+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)+',',@i=@i+8
    else if @columntype='smalldatetime'
     select @str1=@str1+@columnname+'='+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)+',',@i=@i+4
    else if @columntype='int'
     select @str1=@str1+@columnname+'='+rtrim(convert(int,dbo.f_reverseBinary(substring(@s1,@i,4))))+',',@i=@i+4
    else if @columntype='decimal'
     select @str1=@str1+@columnname+'=DECIMAL,',@i=@i+@length
    else if @columntype='bit'
    begin
     set @bitAdd = case when @bitCount=0 then @i else @bitAdd end
     set @bitCount = (@bitCount + 1)%8
     select @str1=@str1+@columnname+'='+rtrim(convert(bit,substring(@s1,@bitAdd,1)&power(2,case @bitCount when 0 then 8 else @bitCount end-1)))+','
      ,@i=@i+case @bitCount when 1 then 1 else 0 end
  --            print rtrim(@bitAdd)+'->'+rtrim(@length)
    end
    set @lib=@lib+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 @i=@i+2
   set @ib=@i + @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<=@lie
   begin
  --        print rtrim(@ib)+'->'+rtrim(@ie)
    select @columnname=name,@length=length,@columntype=typename,@vc=colid-1 from #t where p=2 and pid=@lib
    if dbo.f_reverseBinary(substring(@s1,@TUVLength,1+((@tc-1)/8))) & power(2,@vc) <> 0 
    begin
     select @str1=@str1+@columnname+'=NULL,'
     select @ib=@ie+1,@i=@i+2
     if @count<@lenVar
      set @ie=convert(int,dbo.f_reverseBinary(substring(@s1,@i,2)))
    end
    else if @columntype='varchar'
    begin
     select @str1=@str1+@columnname+'='+convert(varchar(256),substring(@s1,@ib,@ie-@ib+1))+','
     select @ib=@ie+1,@i=@i+2
     set @ie=convert(int,dbo.f_reverseBinary(substring(@s1,@i,2)))
    end
    else if @columntype='nvarchar'
    begin
     select @str1=@str1+@columnname+'='+convert(nvarchar(256),substring(@s1,@ib,@ie-@ib+1))+','
     select @ib=@ie+1,@i=@i+2
     set @ie=convert(int,dbo.f_reverseBinary(substring(@s1,@i,2)))
    end
    set @count=@count+1
    set @lib=@lib+1
   end
   set @str1=left(@str1,len(@str1)-1)

     END
    
    IF @operation ='LOP_MODIFY_ROW'  
    BEGIN
     print   @operation+'修改前值: '+@str
     
     print   @operation+'修改后值:'+@str1
     
    END
    ELSE
 BEGIN
  print @operation+':'+@str
 END
    set @lb=@lb+1
END

drop table #t,#t1

GO

 

3. Will not deal with it, you can contact professionals to solve the problem thoroughly. [email protected]

———————————————

Guess you like

Origin blog.csdn.net/cmddate/article/details/110247130