通过sqlserver日志恢复误删除的数据
sqlserver恢复数据库语句
sqlserver恢复数据库语句SQL Server是一种关系型数据库管理系统,常见于企业级应用程序中。
在使用过程中,可能会出现数据丢失或意外中断的情况,这时就需要使用恢复数据库语句来恢复数据。
下面是针对SQL Server 的恢复数据库语句,包括10个不同的情况。
1. 恢复一个丢失的数据库当数据库文件丢失时,可以使用以下语句来恢复数据库:RESTORE DATABASE db_nameFROM DISK = 'D:\backup\backup_file_name.bak'WITH REPLACE其中,db_name为要恢复的数据库名称,backup_file_name.bak 为备份文件名称。
该语句将从备份文件中恢复数据库,并且覆盖原有的数据库。
2. 恢复一个损坏的数据库当数据库损坏时,可以使用以下语句来恢复数据库:RESTORE DATABASE db_nameFROM DISK = 'D:\backup\backup_file_name.bak'WITH RECOVERY该语句将从备份文件中恢复数据库,并且尝试将数据库恢复为最新状态。
3. 恢复一个数据库到指定的时间点如果需要将数据库恢复到一个指定的时间点,可以使用以下语句:RESTORE DATABASE db_nameFROM DISK = 'D:\backup\backup_file_name.bak'WITH STOPAT = '2022-06-01 12:00:00'该语句将从备份文件中恢复数据库,并且将数据库恢复到指定的时间点。
4. 恢复一个数据库到指定的事务点如果需要将数据库恢复到一个指定的事务点,可以使用以下语句:RESTORE DATABASE db_nameFROM DISK = 'D:\backup\backup_file_name.bak'WITH STOPBEFOREMARK = 'transaction_mark'该语句将从备份文件中恢复数据库,并且将数据库恢复到指定的事务点。
恢复SQLServer被误删除的数据
恢复SQLServer被误删除的数据恢复SQL Server被误删除的数据《》曾经想实现Log Explorer for SQL Server的功能,利⽤ldf⾥⾯的⽇志来还原误删除的数据这⾥有⼀篇⽂章做到了,不过似乎不是所有的数据类型都⽀持在我使⽤SQLSERVER的这些年⾥⾯,⼤部分⼈都会问我⼀个问题:“能不能恢复被删除的数据??”现在,从SQLSERVER2005 或以上版本能很容易能够恢复被删除的数据(注意:这个脚本能恢复下⾯的数据类型的数据⽽且兼容CS 排序规则)imagetextuniqueidentifiertinyintsmallintintsmalldatetimerealmoneydatetimefloatsql_variantntextbitdecimalnumericsmallmoneybigintvarbinaryvarcharbinarychartimestampnvarcharncharxmlsysname让我来⽤demo来解释⼀下我是怎么做到的USE masterGO--创建数据库CREATE DATABASE testGOUSE[test]GO--创建表CREATE TABLE[dbo].[aa]([id][int]IDENTITY(1,1) NOT NULL,[NAME][nvarchar](200) NULL) ON[PRIMARY]GO--插⼊测试数据INSERT[dbo].[aa]( [NAME] )SELECT'你好'GO--删除数据Delete from aaGo--验证数据是否已经删除Select*from aaGo现在你需要创建⼀个存储过程来恢复你的数据-- Script Name: Recover_Deleted_Data_Proc-- Script Type : Recovery Procedure-- Develop By: Muhammad Imran-- Date Created: 15 Oct 2011-- Modify Date: 22 Aug 2012-- Version : 3.1-- Notes : Included BLOB data types for recovery.& Compatibile with Default , CS collation , Arabic_CI_AS.CREATE PROCEDURE Recover_Deleted_Data_Proc@Database_Name NVARCHAR(MAX) ,@SchemaName_n_TableName NVARCHAR(MAX) ,DECLARE@TransactionID NVARCHAR(MAX)DECLARE@AllocUnitID BIGINTDECLARE@AllocUnitName NVARCHAR(MAX)DECLARE@SQL NVARCHAR(MAX)DECLARE@Compatibility_Level INTSELECT@Compatibility_Level= patibility_levelFROM master.sys.databases AS dtbWHERE =@Database_NameIF ISNULL(@Compatibility_Level, 0) <=80BEGINRAISERROR('The compatibility level should be equal to or greater SQL SERVER 2005 (90)',16,1)RETURNENDIF ( SELECT COUNT(*)FROM INFORMATION_SCHEMA.TABLESWHERE[TABLE_SCHEMA]+'.'+[TABLE_NAME]=@SchemaName_n_TableName) =0BEGINRAISERROR('Could not found the table in the defined database',16,1)RETURNENDDECLARE@bitTable TABLE([ID]INT ,[Bitvalue]INT)--Create table to set the bit position of one byte.INSERT INTO@bitTableSELECT0 ,2UNION ALLSELECT1 ,2UNION ALLSELECT2 ,4UNION ALLSELECT3 ,8UNION ALLSELECT4 ,16UNION ALLSELECT5 ,32UNION ALLSELECT6 ,64UNION ALLSELECT7 ,128--Create table to collect the row data.DECLARE@DeletedRecords TABLE([Row ID]INT IDENTITY(1, 1) ,[RowLogContents]VARBINARY(8000) ,[AllocUnitID]BIGINT ,[Transaction ID]NVARCHAR(MAX) ,[FixedLengthData]SMALLINT ,[TotalNoOfCols]SMALLINT ,[NullBitMapLength]SMALLINT ,[NullBytes]VARBINARY(8000) ,[TotalNoofVarCols]SMALLINT ,[ColumnOffsetArray]VARBINARY(8000) ,[VarColumnStart]SMALLINT ,[Slot ID]INT ,[NullBitMap]VARCHAR(MAX))--Create a common table expression to get all the row data plus how many bytes we have for each row.;WITH RowDataAS ( SELECT[RowLog Contents 0]AS[RowLogContents] ,[AllocUnitID]AS[AllocUnitID] ,[Transaction ID]AS[Transaction ID]--[Fixed Length Data] = Substring (RowLog content 0, Status Bit A+ Status Bit B + 1,2 bytes),CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) AS[FixedLengthData]--@FixedLengthData-- [TotalnoOfCols] = Substring (RowLog content 0, [Fixed Length Data] + 1,2 bytes),CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +1,2)))) AS[TotalNoOfCols]--[NullBitMapLength]=ceiling([Total No of Columns] /8.0),CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +1,2)))) /8.0)) AS[NullBitMapLength]--[Null Bytes] = Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [NullBitMapLength] ),SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +3,CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +1,2)))) /8.0))) AS[NullBytes]--[TotalNoofVarCols] = Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [Null Bitmap length] + 2 ),( CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) IN (0x10, 0x30, 0x70 )THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +3+CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],--[ColumnOffsetArray]= Substring (RowLog content 0, Status Bit A+ Status Bit B + [Fixed Length Data] +1, [Null Bitmap length] + 2 , [TotalNoofVarCols]*2 ) ,( CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) IN (0x10, 0x30, 0x70 )THEN SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +3+CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +1,2)))) /8.0))+2,( CASE WHEN SUBSTRING([RowLog Contents 0],1, 1) IN ( 0x10,0x30, 0x70 )THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +3+CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +1,2)))) /8.0)), 2))))ELSE NULLEND ) *2)ELSE NULLEND ) AS[ColumnOffsetArray]-- Variable column Start = Status Bit A+ Status Bit B + [Fixed Length Data] + [Null Bitmap length] + 2+([TotalNoofVarCols]*2),CASE WHEN SUBSTRING([RowLog Contents 0], 1, 1) IN (0x10, 0x30, 0x70 )THEN ( CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +4+CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +1,2)))) /8.0))+ ( ( CASE WHEN SUBSTRING([RowLog Contents 0],1, 1) IN ( 0x10,0x30, 0x70 )THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +3+CONVERT(INT, CEILING(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],CONVERT(SMALLINT, CONVERT(BINARY(2), REVERSE(SUBSTRING([RowLog Contents 0],2+1, 2)))) +1,2)))) /8.0)), 2))))ELSE NULLEND ) *2 ) )ELSE NULLEND AS[VarColumnStart] ,[Slot ID]FROM sys.fn_dblog(NULL, NULL)WHERE AllocUnitId IN (SELECT[Allocation_unit_id]FROM sys.allocation_units allocunitsINNER JOIN sys.partitions partitions ON ( allocunits.type IN (1, 3 )AND partitions.hobt_id = allocunits.container_id)OR ( allocunits.type =2AND partitions.partition_id = allocunits.container_id)WHERE object_id=OBJECT_ID(''+@SchemaName_n_TableName+'') )AND Context IN ( 'LCX_MARK_AS_GHOST', 'LCX_HEAP' )AND Operation IN ( 'LOP_DELETE_ROWS' )AND SUBSTRING([RowLog Contents 0], 1, 1) IN ( 0x10,0x30, 0x70 )/*Use this subquery to filter the date*/AND[TRANSACTION ID]IN (SELECT DISTINCT[TRANSACTION ID]FROM sys.fn_dblog(NULL, NULL)WHERE Context IN ( 'LCX_NULL' )AND Operation IN ( 'LOP_BEGIN_XACT' )AND[Transaction Name]IN ( 'DELETE','user_transaction' )AND CONVERT(NVARCHAR(11), [Begin Time]) BETWEEN@Date_FromAND@Date_To )),--Use this technique to repeate the row till the no of bytes of the row.N1 ( n )AS ( SELECT1UNION ALLSELECT1),N2 ( n )AS ( SELECT1FROM N1 AS X ,N1 AS Y),N3 ( n )AS ( SELECT1FROM N2 AS X ,N2 AS Y),N4 ( n )AS ( SELECT ROW_NUMBER() OVER ( ORDER BY X.n )FROM N3 AS X ,N3 AS Y)INSERT INTO@DeletedRecordsSELECT RowLogContents ,[AllocUnitID] ,[Transaction ID] ,[FixedLengthData] ,[TotalNoOfCols] ,[NullBitMapLength] ,[NullBytes] ,[TotalNoofVarCols] ,[ColumnOffsetArray] ,[VarColumnStart] ,THEN CONVERT(NVARCHAR(1), ( SUBSTRING(NullBytes,n, 1) %2 ))ELSE CONVERT(NVARCHAR(1), ( ( SUBSTRING(NullBytes,n, 1)/[Bitvalue] )%2 ))END ) --as [nullBitMap]FROM N4 AS NumsJOIN RowData AS C ON n <= NullBitMapLengthCROSS JOIN@bitTableWHEREC.[RowLogContents]=D.[RowLogContents]ORDER BY[RowLogContents] ,n ASCFORXML PATH('')), 1, 1, ''), ',', '') )FROM RowData DIF ( SELECT COUNT(*)FROM@DeletedRecords) =0BEGINRAISERROR('There is no data in the log as per the search criteria',16,1)RETURNENDDECLARE@ColumnNameAndData TABLE([Row ID]INT ,[Rowlogcontents]VARBINARY(MAX) ,[NAME] SYSNAME ,[nullbit]SMALLINT ,[leaf_offset]SMALLINT ,[length]SMALLINT ,[system_type_id]TINYINT ,[bitpos]TINYINT ,[xprec]TINYINT ,[xscale]TINYINT ,[is_null]INT ,[Column value Size]INT ,[Column Length]INT ,[hex_Value]VARBINARY(MAX) ,[Slot ID]INT ,[Update]INT)--Create common table expression and join it with the rowdata table-- to get each column details/*This part is for variable data columns*/--@RowLogContents,--(col.columnOffValue - col.columnLength) + 1,--col.columnLength--)INSERT INTO@ColumnNameAndDataSELECT[Row ID] ,Rowlogcontents ,NAME ,cols.leaf_null_bit AS nullbit ,leaf_offset ,ISNULL(syscolumns.length, cols.max_length) AS[length] ,cols.system_type_id ,cols.leaf_bit_position AS bitpos ,ISNULL(syscolumns.xprec, cols.precision) AS xprec ,ISNULL(syscolumns.xscale, cols.scale) AS xscale ,SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) AS is_null ,( CASE WHEN leaf_offset <1AND SUBSTRING([nullBitMap], cols.leaf_null_bit,1) =0THEN ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) >30000THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2))))-POWER(2, 15)ELSE CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2))))END )END ) AS[Column value Size] ,( CASE WHEN leaf_offset <1AND SUBSTRING([nullBitMap], cols.leaf_null_bit,1) =0THEN ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) >30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) <30000THEN ( CASE WHEN[System_type_id]IN (35, 34, 99 ) THEN16ELSE24END )WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) >30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) >30000THEN ( CASE WHEN[System_type_id]IN (35, 34, 99 ) THEN16ELSE24END ) --24WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],[varColumnStart]) <30000THEN ( CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2))))-ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) )WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) <30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) >30000THEN POWER(2, 15)+CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2))))-ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart])END )END ) AS[Column Length] ,( CASE WHEN SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) =1THEN NULLELSE SUBSTRING(Rowlogcontents,( ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) >30000THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2))))-POWER(2, 15)ELSE CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2))))END )- ( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) >30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) <30000THEN ( CASEWHEN[System_type_id]IN (35, 34, 99 )THEN16ELSE24END ) --24WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) >30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) >30000THEN ( CASEWHEN[System_type_id]IN (35, 34, 99 )THEN16ELSE24END ) --24WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) <30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) <30000THEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2))))-ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart])WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) <30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) >30000THEN POWER(2, 15)+CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],[varColumnStart])END ) ) +1,( CASE WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) >30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) <30000THEN ( CASE WHEN[System_type_id]IN (35, 34, 99 )THEN16ELSE24END ) --24WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) >30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) >30000THEN ( CASE WHEN[System_type_id]IN (35, 34, 99 )THEN16ELSE24END ) --24WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) <30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) <30000THEN ABS(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2))))-ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]))WHEN CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2)))) <30000AND ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray], ( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart]) >30000THEN POWER(2, 15)+CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* leaf_offset*-1 ) -1, 2))))-ISNULL(NULLIF(CONVERT(INT, CONVERT(BINARY(2), REVERSE(SUBSTRING([ColumnOffsetArray],( 2* ( ( leaf_offset*-1 ) -1 ) )-1, 2)))), 0),[varColumnStart])END ))END ) AS hex_Value ,[Slot ID] ,FROM@DeletedRecords AINNER JOIN sys.allocation_units allocunits ON A.[AllocUnitId]= allocunits.[Allocation_Unit_Id]INNER JOIN sys.partitions partitions ON ( allocunits.type IN (1, 3 )AND partitions.hobt_id = allocunits.container_id)OR ( allocunits.type =2AND partitions.partition_id = allocunits.container_id)INNER JOIN sys.system_internals_partition_columns cols ON cols.partition_id = partitions.partition_idLEFT OUTER JOIN syscolumns ON syscolumns.id = partitions.object_idAND syscolumns.colid = cols.partition_column_idWHERE leaf_offset <0UNION/*This part is for fixed data columns*/SELECT[Row ID] ,Rowlogcontents ,NAME ,cols.leaf_null_bit AS nullbit ,leaf_offset ,ISNULL(syscolumns.length, cols.max_length) AS[length] ,cols.system_type_id ,cols.leaf_bit_position AS bitpos ,ISNULL(syscolumns.xprec, cols.precision) AS xprec ,ISNULL(syscolumns.xscale, cols.scale) AS xscale ,SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) AS is_null ,( SELECT TOP1ISNULL(SUM(CASE WHEN C.leaf_offset >1THEN max_lengthELSE0END), 0)FROM sys.system_internals_partition_columns CWHERE cols.partition_id = C.partition_idAND C.leaf_null_bit < cols.leaf_null_bit) +5AS[Column value Size] ,syscolumns.length AS[Column Length] ,CASE WHEN SUBSTRING([nullBitMap], cols.leaf_null_bit, 1) =1THEN NULLAND C.leaf_bit_position =0THEN max_lengthELSE0END), 0)FROM sys.system_internals_partition_columns CWHERE cols.partition_id = C.partition_idAND C.leaf_null_bit < cols.leaf_null_bit) +5, syscolumns.length)END AS hex_Value ,[Slot ID] ,FROM@DeletedRecords AINNER JOIN sys.allocation_units allocunits ON A.[AllocUnitId]= allocunits.[Allocation_Unit_Id]INNER JOIN sys.partitions partitions ON ( allocunits.type IN (1, 3 )AND partitions.hobt_id = allocunits.container_id)OR ( allocunits.type =2AND partitions.partition_id = allocunits.container_id)INNER JOIN sys.system_internals_partition_columns cols ON cols.partition_id = partitions.partition_idLEFT OUTER JOIN syscolumns ON syscolumns.id = partitions.object_idAND syscolumns.colid = cols.partition_column_idWHERE leaf_offset >0ORDER BY nullbitDECLARE@BitColumnByte AS INTSELECT@BitColumnByte=CONVERT(INT, CEILING(COUNT(*) /8.0))FROM@ColumnNameAndDataWHERE[System_Type_id]=104;WITH N1 ( n )AS ( SELECT1UNION ALLSELECT1),N2 ( n )AS ( SELECT1FROM N1 AS X ,N1 AS Y),N3 ( n )AS ( SELECT1FROM N2 AS X ,N2 AS Y),N4 ( n )AS ( SELECT ROW_NUMBER() OVER ( ORDER BY X.n )FROM N3 AS X ,N3 AS Y),CTEAS ( SELECT RowLogContents ,[nullbit] ,[BitMap]=CONVERT(VARBINARY(1), CONVERT(INT, SUBSTRING(( REPLACE(STUFF(( SELECT','+ ( CASEWHEN[ID]=0THEN CONVERT(NVARCHAR(1), ( SUBSTRING(hex_Value,n, 1) %2 ))ELSE CONVERT(NVARCHAR(1), ( ( SUBSTRING(hex_Value,n, 1)/[Bitvalue] )%2 ))END ) --as [nullBitMap]FROMN4 AS NumsJOIN@ColumnNameAndDataAS C ON n <=@BitColumnByteAND[System_Type_id]=104AND bitpos =0CROSS JOIN@bitTableWHEREC.[RowLogContents]=D.[RowLogContents]ORDER BY[RowLogContents] ,n ASCFORXMLPATH('')), 1, 1, ''),',', '') ),bitpos +1, 1)))FROM@ColumnNameAndData DWHERE[System_Type_id]=104)UPDATE ASET[hex_Value]=[BitMap]FROM@ColumnNameAndData AINNER JOIN CTE B ON A.[RowLogContents]= B.[RowLogContents]AND A.[nullbit]= B.[nullbit]/**************Check for BLOB DATA TYPES******************************/DECLARE@Fileid INTDECLARE@Pageid INTDECLARE@Slotid INTDECLARE@CurrentLSN INTDECLARE@LinkID INTDECLARE@Context VARCHAR(50)DECLARE@ConsolidatedPageID VARCHAR(MAX)DECLARE@LCX_TEXT_MIX VARBINARY(MAX)DECLARE@temppagedata TABLE([ParentObject] SYSNAME ,[Object] SYSNAME ,[Field] SYSNAME ,[Value] SYSNAME)DECLARE@pagedata TABLE([Page ID] SYSNAME ,[File IDS]INT ,[Page IDS]INT ,[AllocUnitId]BIGINT ,[ParentObject] SYSNAME ,[Object] SYSNAME ,[Field] SYSNAME ,[Value] SYSNAME[ID]INT IDENTITY(1, 1) ,[PAGE ID]VARCHAR(MAX) ,[FILE IDS]INT ,[PAGE IDS]INT ,[Slot ID]INT ,[AllocUnitId]BIGINT ,[RowLog Contents 0_var]VARCHAR(MAX) ,[RowLog Length]VARCHAR(50) ,[RowLog Len]INT ,[RowLog Contents 0]VARBINARY(MAX) ,[Link ID]INT DEFAULT ( 0 ) ,[Update]INT)DECLARE Page_Data_Cursor CURSORFOR/*We need to filter LOP_MODIFY_ROW,LOP_MODIFY_COLUMNS from log for deleted records of BLOB data type& Get its Slot No, Page ID & AllocUnit ID*/ SELECT LTRIM(RTRIM(REPLACE([Description], 'Deallocated', ''))) AS[PAGE ID] ,[Slot ID] ,[AllocUnitId] ,NULL AS[RowLog Contents 0] ,NULL AS[RowLog Contents 0] ,ContextFROM sys.fn_dblog(NULL, NULL)WHERE AllocUnitId IN (SELECT[Allocation_unit_id]FROM sys.allocation_units allocunitsINNER JOIN sys.partitions partitions ON ( allocunits.type IN (1, 3 )AND partitions.hobt_id = allocunits.container_id)OR ( allocunits.type =2AND partitions.partition_id = allocunits.container_id)WHERE object_id=OBJECT_ID(''+@SchemaName_n_TableName+'') )AND Operation IN ( 'LOP_MODIFY_ROW' )AND[Context]IN ( 'LCX_PFS' )AND Description LIKE'%Deallocated%'/*Use this subquery to filter the date*/AND[TRANSACTION ID]IN (SELECT DISTINCT[TRANSACTION ID]FROM sys.fn_dblog(NULL, NULL)WHERE Context IN ( 'LCX_NULL' )AND Operation IN ( 'LOP_BEGIN_XACT' )AND[Transaction Name]='DELETE'AND CONVERT(NVARCHAR(11), [Begin Time]) BETWEEN@Date_FromAND@Date_To )GROUP BY[Description] ,[Slot ID] ,[AllocUnitId] ,ContextUNIONSELECT[PAGE ID] ,[Slot ID] ,[AllocUnitId] ,SUBSTRING([RowLog Contents 0], 15,LEN([RowLog Contents 0])) AS[RowLog Contents 0] ,CONVERT(INT, SUBSTRING([RowLog Contents 0], 7, 2)) ,Context --,CAST(RIGHT([Current LSN],4) AS INT) AS [Current LSN]FROM sys.fn_dblog(NULL, NULL)WHERE AllocUnitId IN (SELECT[Allocation_unit_id]FROM sys.allocation_units allocunitsINNER JOIN sys.partitions partitions ON ( allocunits.type IN (1, 3 )AND partitions.hobt_id = allocunits.container_id)OR ( allocunits.type =2AND partitions.partition_id = allocunits.container_id)WHERE object_id=OBJECT_ID(''+@SchemaName_n_TableName+'') )AND Context IN ( 'LCX_TEXT_MIX' )AND Operation IN ( 'LOP_DELETE_ROWS' )/*Use this subquery to filter the date*/AND[TRANSACTION ID]IN (SELECT DISTINCT[TRANSACTION ID]FROM sys.fn_dblog(NULL, NULL)WHERE Context IN ( 'LCX_NULL' )AND Operation IN ( 'LOP_BEGIN_XACT' )AND[Transaction Name]='DELETE'AND CONVERT(NVARCHAR(11), [Begin Time]) BETWEEN@Date_FromAND@Date_To )/****************************************/OPEN Page_Data_CursorFETCH NEXT FROM Page_Data_Cursor INTO@ConsolidatedPageID, @Slotid,@AllocUnitID, @LCX_TEXT_MIX, @LinkID, @ContextWHILE@@FETCH_STATUS=0BEGINDECLARE@hex_pageid AS VARCHAR(MAX)/*Page ID contains File Number and page number It looks like 0001:00000130.In this example 0001 is file Number & 00000130 is Page Number & These numbers are in Hex format*/SET@Fileid=SUBSTRING(@ConsolidatedPageID, 0,CHARINDEX(':', @ConsolidatedPageID)) -- Seperate File ID from Page IDSET@hex_pageid='0x'+SUBSTRING(@ConsolidatedPageID,CHARINDEX(':',@ConsolidatedPageID)+1, LEN(@ConsolidatedPageID)) ---Seperate the page IDSELECT@Pageid=CONVERT(INT, CAST(''AS XML).value('xs:hexBinary(substring(sql:variable("@hex_pageid"),sql:column("t.pos")) )','varbinary(max)')) -- Convert Page ID from hex to integerFROM ( SELECT CASE SUBSTRING(@hex_pageid, 1, 2)WHEN'0x'THEN3ELSE0END) AS t ( pos )IF@Context='LCX_PFS'BEGINDELETE@temppagedata+', 1) with tableresults,no_infomsgs;');INSERT INTO@pagedataSELECT@ConsolidatedPageID ,@fileid ,@pageid ,@AllocUnitID ,[ParentObject] ,[Object] ,[Field] ,[Value]FROM@temppagedataENDELSEIF@Context='LCX_TEXT_MIX'BEGININSERT INTO@ModifiedRawDataSELECT@ConsolidatedPageID ,@fileid ,@pageid ,@Slotid ,@AllocUnitID ,NULL ,0 ,CONVERT(INT, CONVERT(VARBINARY, REVERSE(SUBSTRING(@LCX_TEXT_MIX,11, 2)))) ,@LCX_TEXT_MIX ,@LinkID ,ENDFETCH NEXT FROM Page_Data_Cursor INTO@ConsolidatedPageID, @Slotid,@AllocUnitID, @LCX_TEXT_MIX, @LinkID, @ContextENDCLOSE Page_Data_CursorDEALLOCATE Page_Data_CursorDECLARE@Newhexstring VARCHAR(MAX);--The data is in multiple rows in the page, so we need to convert it into one row as a single hex value.--This hex value is in string formatINSERT INTO@ModifiedRawData( [PAGE ID] ,[FILE IDS] ,[PAGE IDS] ,[Slot ID] ,[AllocUnitId] ,[RowLog Contents 0_var] ,[RowLog Length])SELECT[Page ID] ,[FILE IDS] ,[PAGE IDS] ,SUBSTRING([ParentObject],CHARINDEX('Slot', [ParentObject]) +4,( CHARINDEX('Offset', [ParentObject])- ( CHARINDEX('Slot', [ParentObject]) +4 ) )-2) AS[Slot ID] ,[AllocUnitId] ,SUBSTRING(( SELECT REPLACE(STUFF(( SELECTREPLACE(SUBSTRING([Value],CHARINDEX(':',[Value]) +1,CHARINDEX('†',[Value])-CHARINDEX(':',[Value])), '†','')FROM@pagedata CWHERE B.[Page ID]= C.[Page ID]AND SUBSTRING(B.[ParentObject],CHARINDEX('Slot',B.[ParentObject])+4,( CHARINDEX('Offset',B.[ParentObject])- ( CHARINDEX('Slot',B.[ParentObject])+4 ) )) =SUBSTRING(C.[ParentObject],CHARINDEX('Slot',C.[ParentObject])+4,( CHARINDEX('Offset',C.[ParentObject])- ( CHARINDEX('Slot',C.[ParentObject])+4 ) ))AND[Object]LIKE'%Memory Dump%'ORDER BY'0x'+LEFT([Value],CHARINDEX(':',[Value]) -1)FORXML PATH('')), 1, 1, ''), '', '')), 1, 20000) AS[Value] ,SUBSTRING(( SELECT'0x'+REPLACE(STUFF(( SELECTREPLACE(SUBSTRING([Value],CHARINDEX(':',[Value]) +1,CHARINDEX('†',[Value])-CHARINDEX(':',[Value])), '†','')FROM@pagedata CWHEREB.[Page ID]=C.[Page ID]AND SUBSTRING(B.[ParentObject],CHARINDEX('Slot',B.[ParentObject])+4,( CHARINDEX('Offset',B.[ParentObject])- ( CHARINDEX('Slot',B.[ParentObject])+4 ) )) =SUBSTRING(C.[ParentObject],。
SQLServer日志恢复还原数据
SQLServer⽇志恢复还原数据通过⽇志还原,⾸先要注意的是:
1,在数据库更新和删除之前有⼀个完整的备份。
2,在更新和删除之后,做⼀个⽇志备份。
3,该⽇志只能⽤于还原数据库备份和⽇志备份时间之间的数据。
下⾯看整个数据库备份和恢复的操作流程:
1,创建⼀个数据库并完整备份:
新建⼀个表:
然后进⾏数据库的备份:
右键数据库(Db)-任务-备份:
先把默认的备份路径删除,要不然后⾯会出错,然后点添加:
然后选中刚才添加的路径,点确定:
2,误删除操作
假设我们误操作删除了这个表,注意删除表的时间,后⾯会⽤到:
3,这个时候需要备份⽇志⽂件:
BACKUP LOG Db TO DISK='d:\Db_log.bak' WITH FORMAT GO
4,还原数据库
任务-还原-数据库
右键-任务-还原-事务⽇志
需要注意的是选择的时间⼀定要在备份数据库和备份⽇志⽂件之间
⼤功告成:。
SQLSERVER 数据恢复
数据库误操作数据恢复还原出现问题,处于正在还原状态的取消命令在master数据库下执行RESTORE DATABASE数据库名WITH RECOVERY数据恢复备份有两种方法。
第一种从备份中恢复数据1.总体操作步骤:1.先停止服务以免新的数据进来。
造成恢复到以前的时间点后,新的数据无法恢复。
2. 必须在出现问题之前做过完整备份。
3. 在完整备份基础上做一次尾部日志备份。
4. 还原事务日志,选择最后一次完整备份的数据库及尾部日志进行还原。
先还原的是数据库,再还原尾部日志,还原尾部日志时要选择还原到的时间点,最好精确到秒。
等待还原完成。
2.注意事项:1. 在做尾部日志恢复之前,曾经做过最少一次的完整备份。
因为所有类型的备份都基于完整备份,如果没有最少一次完整备份,其他类型的备份都是多余的,所以在这里强调一下,在创建完一个新数据库之后,强烈建议甚至强制做一次完整备份。
2. 在出现操作失误之后不要做数据库的完整备份------SQL------1. 查看那些数据库做过备份SELECT database_name,recovery_model,name FROM msdb.dbo.backupset2. 还原出现问题,处于正在还原状态的取消命令在master数据库下执行RESTORE DATABASE数据库名WITH RECOVERY3.具体操作方法1)备份物理源文件在出现操作失误之后不要做数据库的完整备份,先做MDF和LDF物理源文件备份。
将数据库文件复制一份保存。
2)备份日志尾部选择要备份日志的数据库,右键选择任务-》备份。
在常规中备份类型选择【事物日志】选择介质选项。
在可靠性中勾选【完成后验证备份】和【写入介质前检查校验】,在事务日志中勾选【备份日志尾部,并使数据库处于还原状态】选择备份选项,在压缩选项中选压缩备份,确定备份此时数据库会处于【正在还原状态】如果发现备份不了可以用下面语句查看,并把spid杀掉后继续备份---查询数据库IDselect * from sys.databases---查询数据库的连接SELECT * FROM sys.sysprocesses WHERE dbid=数据库ID---删除数据库连接Kill (spid号)如:kill 333)还原完整备份选择还原【文件和文件组】,在【常规】中选择完整备份的数据库,先要还原完整备份,选择最近的那次,由于日志备份的特性,只认最后一次备份,所以要选择最新的那次,否则还原不了。
sqlserver还原数据库步骤
sqlserver还原数据库步骤1.备份恢复步骤:(1)首先进入sql server management studio管理工具,在对象资源管理器中,右击“数据库”,在菜单中点击“任务”-“恢复数据库”;(2)在“恢复数据库”窗口中,第一步,点击数据库名称列表,然后选择要还原到的目标数据库名称;(3)第二步,点击“源”,在“重新定位文件”下,点击该子窗口,在新弹出的“此文件组对话框”中,选择“从备份文件中恢复文件”,然后点击“浏览…”,找到备份文件的路径,然后点击“确定”。
(4)第三步,点击“选项”,选中“替换当前数据库”,然后点击“恢复”,最后点击“确定”,还原就完成了。
说明:如果恢复的是空数据库,可以不用上述设置步骤,直接选择要恢复的数据库,然后把文件组、源、重新定位文件三个步骤全部跳过,进入选项步骤,在里面选择“恢复”,然后点击“确定”完成还原。
2.覆盖恢复步骤:(1)首先在sql server management studio管理工具中,右击“数据库”,在菜单中点击“任务”-“恢复数据库”;(2)然后在“恢复数据库”窗口中,第一步,点击数据库名称列表,然后选择要还原到的目标数据库名称;(3)第二步,点击“源”,在“重新定位文件”下,点击该子窗口,在新弹出的“此文件组对话框”中,选择“从备份文件中恢复文件”,然后点击“浏览…”,找到备份文件的路径,然后点击“确定”;(4)第三步,点击“选项”,主要选中“覆盖此数据库”,然后点击“恢复”,最后点击“确定”,完成还原。
3.日志恢复步骤:(1)首先进入sql server management studio管理工具,在对象资源管理器中,右击“数据库”,在菜单中点击“任务”-“恢复数据库”;(2)然后在“恢复数据库”窗口中,第一步,点击数据库名称列表,然后选择要还原到的目标数据库名称;(3)第二步,点击“源”,在“重新定位文件”下,点击该子窗口,在新弹出的“此文件组对话框”中,选择“从日志文件中恢复文件”,然后点击“浏览…”,找到备份文件的路径,然后点击“确定”;(4)第三步,点击“选项”,主要选中“恢复数据库:追加到现有数据库”,然后点击“恢复”,最后点击“确定”,完成还原数据库操作。
sqlserverupdate或者Delete误操作恢复方法---【验证】
sqlserverupdate或者Delete误操作恢复⽅法---【验证】具体⽅法:经验教训:1、新建数据库⼀定要做⼀次全备份;2、制定定时计划任务做数据备份;3、决不能直接把开发环境连接⽣产数据库;4、做技术,尤其是做数据相关的技术,是要很严谨的,决不能掉以轻⼼,时时刻刻保持严谨之⼼;灾难情况概述:在执⾏Update语句的时候,忘记添加Where条件,没有⽤事务,导致3000多条重要数据被我搞成⼀个模样。
真是脑袋⼀热啊,⼀个按钮点下去全完蛋,⽽且之前还不备份。
灾难应急过程:当时慌了神,但咬着⽛告诉⾃⼰要冷静,脑海⾥n多后果浮想联翩,⾸先使⽤关键词“sqlserver update 误操作恢复”百度⼀顿搜,没有⽅案,很多⼈说没有备份不能恢复;然后相同关键词搜⾕歌,也没有;最后加了个sql QQ群,点了⼏个管理员⼀通问,有两个回答的,其中⼀个说没有备份不⾏,另⼀个说使⽤⽇志可以恢复。
然后,我改变关键词sqlserver⽇志还原恢复,结果看到了这个救命的⽂章,新建测试数据库,按照步骤⾛了⼀遍果然OK,然后把⽣产数据库数据⽂件和⽇志⽂件,以及3个⽉前的⼀个完整数据库备份拷贝到另⼀台电脑上,进⾏附加,然后按照原⽂步骤进⾏还原,果然,我的数据回来了整个过程历时四个⼩时,太漫长了,那么多⼈都说不可以,但有⼀线希望我们决不放弃,如果我放弃了,命运可能就此变化了!关键点总结使⽤原⽂⽅法需要满⾜以下条件,原⽂博主也说的很清楚了,我再叙述⼀遍:1、数据库恢复模式为完整,不是的改过来;2、曾经完整备份过数据库,这⼀点我是11⽉14号发⽣的这件事,找到了7⽉30号的⼀个完整备份(.bak⽂件)具体操作步骤,请查看原⽂,请坚定的按照步骤⾛下去,过程中可能会因为操作不当或者其他原因,有些错误提⽰,记住可以采取删掉重新附加、关掉管理环境重新打开等⽅式。
再次感谢原⽂作者:發糞塗牆以及QQ朋友:风扬/浅尾,希望这种有价值,有巨⼤意义的好⽂章越来越多。
SQLSERVER数据误操作的恢复
SQLSERVER数据误操作的恢复SQL SERVER 数据误操作的恢复事务⽇志忠实地记录了数据库的活动,所以基于这些记录的活动就可以随⼼所欲地将数据库的状态恢复到特定的即时点或故障点。
事务⽇志备份只能与完整恢复和⼤容量⽇志记录恢复模型⼀起使⽤。
在简单模型下,事务⽇志可能被破坏,所以事务⽇志可能不连续,不连续的事务⽇志备份没有意义,因为基于⽇志的恢复要求⽇志是连续的。
因为有了连续的、完整的事备⽇志序列,配合⼀个完整的数据库备份,我们可以将数据库的状态恢复到⽇志序列中的任意⼀个即时点。
恢复数据到即时点有两个前提:n正确的完整数据库的最后⼀次备份正确完整的数据库备份是指使⽤Backup语句、维护计划、⼿动备份的备份⽂件,不⽀持基于数据库⽂件*.mdf的备份n正确的即时点即所要恢复到数据的时间点实例:1.创建数据DBTEST2.创建表TBL_TEST3.在表TBL_TEST中插⼊100条数据4.备份现有的数据库5.再次向表TBL_TEST中插⼊50条数据6.记录下当前正确数据的时间d17.2分钟模拟误操作将表中所有数据删除8.备份数据库尾⽇志9.将数据库恢复到d1时间1)创建数据DBTESTCREATE DATABASE DBTEST2)创建表TBL_TESTCREATE TABLE TBL_TEST(ID [int] NOT NULL PRIMARY KEY,NAME [datetime] NOT NULL,ADDRESS varchar(50)NOT NULL)3)在表TBL_TEST中插⼊100条数据use DBTESTuse DBTESTdeclare @i intset @i=1while(@i<=100)beginINSERT INTO TBL_TEST VALUES(@i,getdate(),'ADDRESS '+ convert(varchar(50),@i))set @i=@i+1endselect*from TBL_TEST4)备份现有的数据库--做⼀次完整数据库备份backup database DBTEST to disk='C:"DBTEST.bak'5)再次向表TBL_TEST中插⼊50条数据use DBTESTdeclare @i intset @i=101while(@i<=150)beginINSERT INTO TBL_TEST VALUES(@i,getdate(),'ADDRESS '+ convert(varchar(50),@i))set @i=@i+1endselect*from TBL_TEST6)记录下当前正确数据的时间d1当前时间为:2008-5-26 20:137)2分钟模拟误操作将表中所有数据删除DELETE TBL_TEST8)备份数据库尾⽇志use masterbackup log DBTEST to disk='C:"DBTESTLOG.bak'with norecovery--将数据库恢复到d1时间误删除的数据已经恢复!。
sql server恢复方法
sql server恢复方法SQL Server是一种关系型数据库管理系统(RDBMS),用于存储和管理数据库。
在日常操作中,可能会遇到各种数据丢失或损坏的情况,因此需要进行恢复操作来恢复数据库的完整性和可用性。
下面将介绍SQL Server常见的恢复方法。
一、完整备份恢复完整备份是指备份整个数据库的过程,包括数据、存储过程、触发器、索引等。
如果数据库损坏或丢失,可以通过完整备份来恢复数据库。
1.创建完整备份:使用SQL Server Management Studio(SSMS)或T-SQL命令创建完整备份。
例如,使用SSMS,右键点击数据库->任务->备份,在“选择备份类型”中选择“完整”,并设置备份路径、名称等参数,然后点击“确定”开始备份。
2.恢复完整备份:使用SSMS或T-SQL命令进行恢复。
例如,使用SSMS,右键点击数据库->任务->还原->数据库,在“设备”中选择备份文件,设置恢复操作的目的数据库名称等参数,然后点击“确定”开始恢复。
二、差异备份恢复差异备份是指备份数据库中自上次完整备份以来的更改。
使用差异备份可以减少备份时间和存储空间。
如果数据库部分数据丢失或损坏,可以先恢复完整备份,然后再将差异备份应用到数据库中,以恢复数据到更精确的时间点。
1.创建差异备份:在完整备份后,可以使用SSMS或T-SQL命令创建差异备份。
例如,使用SSMS,在“选择备份类型”中选择“差异”,设置备份路径、名称等参数,然后点击“确定”开始备份。
2.恢复差异备份:使用SSMS或T-SQL命令进行恢复。
例如,使用SSMS,右键点击数据库->任务->还原->数据库,在“设备”中选择差异备份文件,设置恢复操作的目的数据库名称等参数,然后点击“确定”开始恢复。
三、事务日志备份恢复事务日志是用于记录数据库操作的日志文件,包括对数据库的修改、事务的提交和撤销等。
事务日志备份可以实时记录数据库操作,以便在数据库发生故障时进行恢复。
SQLserver数据库恢复
让知识带有温度。
SQLserver数据库恢复前几天由于一个例外,数据库在没有做备份的状况下,直接删除了表记录。
事后,又需要查询到删除的记录的内容。
因此,在网上软件SS了半天,发觉Log Exlorer For SQL Service 能实现将表操作日志显示出来的功能。
下载安装使用后,发觉这款软件确实不错,保藏ing。
本次的使用的VER:4.2 Demo; 数据库:SQL2022; 目的:恢复被删除的数据。
所以,只略说了恢复数据的步骤。
4.2Demo的界面以蓝色为主调,运行软件可见:(1).点击开头举行数据恢复。
(2).确定要恢复数据的服务器,并输入登陆的用户名和密码,假如是本机可使用”windows 身份验证”,点击测试衔接。
(3).挑选要恢复数据所在有数据库,点击进入数据操作界面。
(4).进入数据操作界面后,在左边的菜单挑选,可显示操作的日志,例如是对哪一个表举行过新增、删除、修改等操作,操作的记录是什么内容都能显示出来。
假如日志长时光没有清空过,那么这些日志就会无数,可以用“过滤功能”来设置条件举行日志筛选。
第1页/共2页千里之行,始于足下可以按照时光,表,用户等的条件来举行筛选。
(5).查询出来的日志内容,可以导出XML文件。
导入的XML文件假如想转入数据库,则需自己写代码分析XML文件。
注重:删除数据时需当心,不是全部的数据都能恢复;恢复的数据操作属于正常的操作。
PS:假如是一个数据备份文件*.bak之类的文件恢复之后,原有的操作日志用LogSql 有可能查询不到,这一点我已阅历证了。
文档内容到此结束,欢迎大家下载、修改、丰富并分享给更多有需要的人。
第2页/共2页。
通过sqlserver日志恢复误删除的数据
通过sqlserver日志恢复误删除的数据如果你已经急的焦头烂额,看到这篇文章的时候,请你换个坐姿,深呼吸几次,静下心来将这篇文章读完,也许你的问题迎刃而解。
我遇到的情况是这样的,网站被植入木马,盗取了我的web.config文件,web.config文件里面的数据库连接字符串没有加密,而我的数据库远程连接又没有做IP限制,黑客通过数据库客户端连上我的数据库后,将所有的表都Delete掉了,所以大家一定要有一个好习惯将数据库连接字符串加密或者对远程访问数据库的IP作限制。
因被黑客Delete掉所有数据的具体时间点我不清楚,所以我就用了一个工具Log Explorer来查看分析数据库日志,看具体是什么时候被Delete掉的(若你已经知道想要还原的时间点,就不用使用此工具啦),至于Log Explorer如何安装使用的,这里就不赘述了,去百度一搜一大堆,安装的时候Client和Server 都选,然后安装中会有一步让你输入数据库的用户名和密码,其他不懂的就疯狂下一步吧。
通过Log Explorer工具我查看到被删除的时间点是:07-10 09:46:29.880,那我一会把数据还原到07-10 09:46:29.879就好咧下面开始言归正传的进行恢复操作了1、将数据库日志备份一下,用T-Sql语句2、因我的数据库每天都有自动完整备份,找一个最近时间的完整备份,来还原一下,这里我不往旧库覆盖了,直接还原成一个新的数据库shua2用SQL Server Management Studio工具进行界面操作吧,写sql语句还原太复杂了,不会啊。
对着数据库->右击->还原数据库,下图是我在[还原数据库]界面->[常规]选项卡页的填写情况然后点【选项】选项卡页,注意这一步非常重要哦点击【不对数据库执行任何操作,不回滚来提交的事务】,然后确定。
如果数据库比较大,这个还原要等很长时间,出去吸几口新鲜空气吧,大功就要告成了。
SQLSERVER只有ldf日志文件如何恢复数据
SQLSERVER只有ldf日志文件如何恢复数据数据库文件损坏的时候如何恢复1 建一个测试数据库test(数据库类型为完全)2 建一个表,插入点记录create table a(c1 varchar(2))goinsert into a values('aa')goinsert into a values('bb')go3 作完全备份,到文件test_1.bak4 在作一点修改insert into a values('cc')gocreate table b(c1 int)goinsert into b values(1)goinsert into b values(2)go5 shutdown 数据库服务器6 用ultraedit编辑数据库文件test_data.mdf,随便修改点字节内容7 启动数据库,并且运行企业管理器,点开数据库,看到test变成灰色,而且显示置疑。
8 运行isql -SLocalhost -Usa -P1> backup log test TO DISK='D:\Program Files\Microsoft SQL Server\MSSQL\BACKUP\test_2.bak' WITH NO_TRUNCATE2>go已处理2 页,这些页属于数据库'test' 的文件'TEST_Log'(位于文件 1 上)。
BACKUP LOG 操作成功地处理了2 页,花费了0.111 秒(0.087 MB/秒)。
9 进行恢复最老的完全备份1> RESTORE DATABASE test from DISK='D:\Program Files\Microsoft SQL Server\MSSQLBACKUP\test_1.bak' WITH NORECOVERY注意一定要有WITH NORECOVERY选项2> go已处理96 页,这些页属于数据库'test' 的文件'TEST_Data'(位于文件 1 上)。
SQLServer 2008以上误操作数据库恢复方法
SQLServer 2008以上误操作数据库恢复方法——日志尾部备份问题:经常看到有人误删数据,或者误操作,特别是update和delete的时候没有加where,然后就喊爹喊娘了。
人非圣贤孰能无过,做错可以理解,但不能纵容,这个以后再说,现在先来解决问题。
遇到这种情况,一般都是没有做备份,不然也不会来发问了。
首先要冷静,否则会有更大的灾难。
直到你放弃。
解决方法:对于这类问题,主要是找回误操作之前的数据,在2008之前,有个很出名的工具Log Exploer,听说还挺好用的,这个网上大把教程,这里就不多说了。
但是唯一遗憾的是,不支持2008及更高版本,这时除了其他第三方工具,那么最常用的就是本文提到的方法——日志尾部备份。
本文实验环境2008R2,对于2008及其以上版本可以使用这个方法,其实2005也可以,2000很少用,没试过,只是2008之前可以使用Log Exploer,所以就没必要用这种方法。
下面图文并茂讲解操作方法,至于原理,不属于本文范围,而且我相信真遇到误操作的时候,估计没人会看原理了。
步骤:(1)、检查数据库的恢复模式,如图:或者使用脚本检查:[sql]view plaincopyprint?1.SELECT recovery_model,recovery_model_desc2.FROM sys.databases3.WHERE name ='AdventureWorks'结果如下:确保数据库的恢复模式最起码不能为【简单】。
至于如何修改成完整模式,我觉得这些应该没必要多说了。
切记,对于任何重要环境,不仅仅是客户正式环境(俗称生产环境),都强烈建议使用【完整恢复模式】,虽然对于另外两种(大容量日志(BULK_LOGGED)、简单(SIMPLE))来说,完整恢复模式产生的日志会大,但是在出现问题的时候,就会觉得这些都不算什么了。
并且我也想不到任何理由对于正式环境不使用完整恢复模式。
误删SQL Server数据用使用日志恢复
误删SQL Server数据用LogExplorer恢复数据库技巧2010-07-28 09:48参考一:恢复误删数据(SQL Server 2000)用Log Explorer不小心把客户那边的数据库中删了一千多条数据,之前又没有备份,很郁闷,后来在网上找到一工具(Log Explorer),让我躲过一劫。
首先看一下界面:输入服务器地址,用户名及密码后点Connect,进入界面:在这里选择要恢复数据的数据库,选择UseOn-lineLog(假如你又备份文件的话就不需要用这个工具了,直接用SQL搞定了)。
然后点Attach,进入界面:可以看到左边菜单中有很多功能,我们要恢复数据,首先要查看日志,找出误操作的那些日志记录,点Browse下的ViewLog:这样我们看到对于这个数据库的所有操作日志,我们可根据日期等条件来过滤出我们需要的:过滤日志之后,就到导出数据这一步,这个工具提供了两种方式,第一是导出到XML或HTML文件中(对应左边菜单中的ExportToFile),第二是直接在数据库中建新表,然后将数据导入(ExportToSQL)。
我们来看一下导入到SQL的情况,首先点ExportToSQL选项:输入Database及Table的名称,然后Finish。
这样在你数据的数据库中就会看到有这样几个表:TestTable TestTable_dll TestTable_details TestTable_Keys TestTable_Login其中恢复的数据就在TestTable_details 表中,不过数据格式已经变了,你还需要写存储过程或用其它方法把它导入到原来的表中。
由于大小已超过限制,没有将工具传上来,不过网上有很多地方提供下载,假如你需要,请留下Email。
(网络人 asp教程网)参考资料:/341437.html参考二:误删数据情况下数据库的恢复昨天公司发生一个灾难,日报系统SQLSERVER上的所有数据被一个冒失的家伙全部删除了。
sqlserver事务写法 delete数据恢复
sqlserver事务写法delete数据恢复在SQL Server 中,如果你在事务中执行了DELETE 操作并且想要恢复这些被删除的数据,有几种方法可以实现这一目标。
以下是其中的一些方法:1. 使用事务回滚如果还没有提交事务,你可以简单地回滚事务以撤销所做的更改。
例如:SQLBEGIN TRANSACTION;DELETE FROM your_table WHERE some_condition;-- 如果想要撤销更改,可以使用以下命令ROLLBACK TRANSACTION;2. 使用备份和还原如果你已经提交了事务并且想要恢复数据,你可能需要从备份中还原数据。
确保你有一个最近的备份,并且该备份包含你想要恢复的数据。
3. 使用日志挖掘如果你的数据库启用了事务日志记录,你可以使用SQL Server 的日志挖掘功能来恢复被删除的数据。
这通常涉及到使用DBCC LOG 命令来查看事务日志的内容,并找到你想要恢复的数据的条目。
4. 使用第三方工具有一些第三方工具,如ApexSQL Recover、Stellar ReCOVER 等,可以帮助你恢复被删除的数据。
这些工具使用数据库的底层机制来尝试恢复丢失的数据。
5. 直接从备份中恢复数据如果你有定期备份你的数据库,并且这些备份包含了被删除的数据,你可以直接从备份中恢复数据。
确保你选择正确的备份集,并遵循适当的步骤来恢复数据。
注意事项:•在执行任何数据恢复操作之前,确保你已停止对数据库的所有写操作,以避免进一步的数据丢失或损坏。
•如果可能的话,在进行任何数据恢复操作之前,创建一个当前的快照或完整备份,以防止进一步的意外发生。
•根据你的具体情境和需要选择最合适的数据恢复方法。
如果数据非常重要并且难以替换,可能值得寻求专家的帮助或在适当的情境下采取法律行动来保护你的权益。
SQLServer数据库使用日志备份还原至指定时间点
SQLServer数据库使⽤⽇志备份还原⾄指定时间点SQLServer数据库使⽤⽇志备份还原⾄指定时间点现场正常情况:某客户数据库数据⽂件约1T,⽇志⽂件忽略⼤⼩,每⽇凌晨0点做数据库完整备份,每⽇中午12点做数据库差异备份。
异常问题:某⽇晚19点01分,因某误操作,导致某⼤表近2亿条数据被删除,约19点30分,发现问题,客户分别在19点31分、19点50分、20点00分执⾏了⽇志备份(本⽂为了简化说明,假定备份均⽴即完成,实际备份过程中产⽣数据及耗时不做考虑),之后在20点30分做数据库全备,最后请求⽀持。
⽀持处理操作:1、⽴即断开前台业务,确保不再有新业务写⼊(否则新写⼊的业务会在恢复时丢失)2、由于客户最后⼜做了⼀次数据库全备,因此可以直接忽略最后⼀次完备。
协调客户使⽤新服务器。
3、⾸先还原当⽇凌晨0点数据库备份,并将数据库处于还原模式4、继续还原当⽇12点数据库差异备份,同样处于还原模式(该步骤实际可以忽略)5、最后还原晚上做的第⼀次⽇志备份,注意还原时选择时间点为19点00分00秒,选在回滚事务。
6、检查数据库数据情况,若仍有数据误删情况,考虑重复还原数据库⽇志(需要先将数据库调整成还原状态),并调整还原时间点。
备注:第4步所谓的可以忽略是因为差异备份与完整备份之间相差时间不长,但假如情况如下:周⼀0点完备,周⼆、周三、周四、周五12点差异备份,在周五18点进⾏⽇志备份,此时想将数据恢复⾄17点。
此时同样可以直接使⽤周⼀0点的完备+周五18点的⽇志备份。
但⽇志备份数据量较⼤,耗时可能较长;也可以使⽤周⼀0点完备+周五12点差异备份,加周五18点⽇志备份,这样耗时相对较短。
总结:⽇志恢复的重点在于上⼀次的完整备份,如果有多个⽇志备份,那么就按照时间先后顺序,逐个还原⽇志备份。
SQLServer数据恢复
SQLServer数据恢复1.从⽇志恢复数据库--创建测试数据库CREATE DATABASE DbGO--对数据库进⾏备份BACKUP DATABASE Db TO DISK='c:\db.bak' WITH FORMATGO--创建测试表CREATE TABLE Db.dbo.TB_test(ID int)--延时1秒钟,再进⾏后⾯的操作(这是由于SQL Server的时间精度最⼤为百分之三秒,不延时的话,可能会导致还原到时间点的操作失败) WAITFOR DELAY '00:00:01'GO--假设我们现在误操作删除了 Db.dbo.TB_test 这个表DROP TABLE Db.dbo.TB_test--保存删除表的时间SELECT dt=GETDATE() INTO #GO--在删除操作后,发现不应该删除表 Db.dbo.TB_test--下⾯演⽰了如何恢复这个误删除的表 Db.dbo.TB_test--⾸先,备份事务⽇志(使⽤事务⽇志才能还原到指定的时间点)BACKUP LOG Db TO DISK='c:\db_log.bak' WITH FORMATGO--接下来,我们要先还原完全备份(还原⽇志必须在还原完全备份的基础上进⾏)RESTORE DATABASE Db FROM DISK='c:\db.bak' WITH REPLACE,NORECOVERYGO--将事务⽇志还原到删除操作前(这⾥的时间对应上⾯的删除时间,并⽐删除时间略早DECLARE @dt datetimeSELECT @dt=DATEADD(ms,-20,dt) FROM # --获取⽐表被删除的时间略早的时间RESTORE LOG Db FROM DISK='c:\db_log.bak' WITH RECOVERY,STOPAT=@dtGO--查询⼀下,看表是否恢复SELECT * FROM Db.dbo.TB_test/*--结果:ID-----------(所影响的⾏数为 0 ⾏)--*/--测试成功GO--最后删除我们做的测试环境DROP DATABASE DbDROP TABLE #2.利⽤⼯具恢复 ApexSQLLog2016破解版,但是破解版读取Log⽂件时,容易崩溃,需要耐⼼的多试⼏次(亲测可⽤)。
MSSqlServer通过数据库日志文件找回已删除的记录
MSSqlServer通过数据库⽇志⽂件找回已删除的记录1.建⽴演⽰数据(创建数据库数据表添加基础数据)
1.1 创建数据库
1.2 创建数据表
1.3填充数据
1.4做数据库完整备份
2.模拟误删除、记录操作时间、备份数据库⽇志2.1删除数据并记录操作时间
2.2⽴即进⾏⽇志备份
3.1将完整备份的数据库⽂件还原为⼀个新库testdb_bak
还原成功后,备份库是下图这样的
3.2 还原⽇志。
在备份库上右键=>任务=>还原=>事务⽇志 选择源设备
选择备份集
选择还原到的时间点(⽐误操作早的时间点)
3.3 点击保存,还原成功!
4.其他
4.1整个步骤需要两个备份,⼀个是完整备份,⼀个是⽇志备份。
完整备份其实就是还原数据结构、⽇志备份是为了还原数据。
4.2 是⼀般⼤型⽹站数据安全的⼀个办法,因为数据库⽐较⼤(可能有⼏百G)数据,做⼀次完整备份时间很长,⽽且影响数据库服务器的性能,为保证数据安全,⼤多采⽤完整备份+事务⽇志备份来保证数据安全。
例如:⼀天做⼀次或者2天做⼀次完整备份,⼏个⼩时内做⼀次⽇志备份。
(当然可以⽤写⼀个job来实现)
4.3如果恢复的⽇志数据出现”LSN“太早和太晚说明了事务⽇志间的不连续。
这时要注意备份的时间和顺序。
SQLSERVER回滚恢复误操作的数据
SQLSERVER回滚恢复误操作的数据在⽣产数据库做CURD操作时,可能会有执⾏某条语句误操作的情况发⽣,针对这个种情况有两点建议:1、在SQL SERVER上开启事务确认功能,当执⾏完语句后确认⽆误,再提交事务。
(开启⽅法见附件图⽚)。
2、新建存储过程,粘贴附件脚本。
此存储过程执⾏后能够⾃动产⽣两个操作⽇志表,⾃动记录CRUD的所有操作。
适⽤于提交事务后才发现错误的情况。
只需要打开表UPDATE_LOG,粘贴RollbackupSQL⾥的语句执⾏即可恢复数据。
注意:1)如果表中有⾃增长的ID,所恢复数据的ID值是最⼤ID+1。
2)由于正常操作也会回写操作⽇志,注意及时清理⽇志表,或者在执⾏完后删掉新建的存储过程、触发器及表。
回滚脚本,执⾏后数据要记录的表名CREATE PROCEDURE[dbo].[SP_UPDATE_LOG]@TABLENAME VARCHAR(50)ASBEGINSET NOCOUNT ON;IF NOT EXISTS(SELECT*FROM sys.tables WHERE NAME =@TABLENAME AND TYPE ='U' )BEGINPRINT'ERROR:not exist table '+@TABLENAMERETURNENDIF (@TABLENAME LIKE'BACKUP_%'OR@TABLENAME='UPDATE_LOG' )BEGIN--PRINT'ERROR:not exist table '+@TABLENAMERETURNEND--================================判断是否存在 UPDATE_LOG 表============================IF NOT EXISTS(SELECT*FROM sys.tables WHERE NAME ='UPDATE_LOG'AND TYPE ='U')CREATE TABLE UPDATE_LOG(UpdateGUID VARCHAR(36),UpdateTime DATETIME,TableName varchar(20),UpdateType varchar(6),RollBackSQL varchar(MAX),ExecSQL VARCHAR(500))--=================================判断是否存在 BACKUP_ 表================================IF NOT EXISTS(SELECT*FROM sys.tables WHERE NAME ='BACKUP_'+@TABLENAME AND TYPE ='U')BEGINDECLARE test_Cursor CURSOR FORSELECT COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.columnsWHERE TABLE_NAME=@TABLENAMEOPEN test_CursorDECLARE@SQLTB NVARCHAR(MAX)=''DECLARE@COLUMN_NAME NVARCHAR(50),@DATA_TYPE VARCHAR(20),@CHARACTER_MAXIMUM_LENGTH INTFETCH NEXT FROM test_Cursor INTO@COLUMN_NAME,@DATA_TYPE,@CHARACTER_MAXIMUM_LENGTHWHILE@@FETCH_STATUS=0BEGINSET@SQLTB=@SQLTB+'['+@COLUMN_NAME+'] '+@DATA_TYPE+CASE ISNULL(@CHARACTER_MAXIMUM_LENGTH,0) WHEN0THEN''WHEN-1THEN'(MAX)'ELSE'('+CAST(@CHARACTER_MAXIMUM_LENGTH FETCH NEXT FROM test_Cursor INTO@COLUMN_NAME,@DATA_TYPE,@CHARACTER_MAXIMUM_LENGTHENDSET@SQLTB='CREATE TABLE BACKUP_'+@TABLENAME+' (UpdateGUID varchar(36),UpdateType Varchar(10),'+SUBSTRING(@SQLTB,1,LEN(@SQLTB)-1)+')'EXEC (@SQLTB)CLOSE test_CursorDEALLOCATE test_CursorEND--======================================判断是否存在 UPDATE 触发器=========================IF NOT EXISTS(SELECT*FROM sys.objects WHERE NAME ='tg_'+@TABLENAME+'_Update'AND TYPE ='TR')BEGINDECLARE@SQLTR NVARCHAR(MAX)SET@SQLTR='CREATE TRIGGER tg_'+@TABLENAME+'_UpdateON '+@TABLENAME+'AFTER Update,Delete,InsertASBEGINSET NOCOUNT ON;--==============================获取GUID==========================================DECLARE @NEWID VARCHAR(36)=NEWID()--===========================将删掉或新增的数据插⼊备份表=========================DECLARE @ROWCOUNT INTINSERT INTO [dbo].[BACKUP_'+@TABLENAME+']SELECT @NEWID,''DELETE'',* FROM deletedSET @ROWCOUNT=@@ROWCOUNTIF @ROWCOUNT>0BEGININSERT INTO [dbo].[BACKUP_'+@TABLENAME+']SELECT @NEWID,''INSERT'',* FROM insertedENDELSEBEGININSERT INTO [dbo].[BACKUP_'+@TABLENAME+']SELECT @NEWID,''INSERT'',* FROM insertedSET @ROWCOUNT=@@ROWCOUNTEND--==============================记录⽇志和回滚操作的SQL===========================--******************⽣成插⼊语句⽤到的列名(需避开⾃增字段)********************DECLARE @COLUMN1 NVARCHAR(MAX)=''''SELECT @COLUMN1+='',[''+COLUMN_NAME+'']'' FROM INFORMATION_SCHEMA.columnsWHERE TABLE_NAME='''+@TABLENAME+'''AND COLUMNPROPERTY(OBJECT_ID('''+@TABLENAME+'''),COLUMN_NAME,''IsIdentity'')<>1 --⾮⾃增字段SET @COLUMN1=SUBSTRING(@COLUMN1,2,LEN(@COLUMN1))--*******************动态定义变量、删除条件匹配的列********************DECLARE @DECLARE VARCHAR(MAX)='''',@INTODECLARE VARCHAR(MAX)='''',@WHERE VARCHAR(MAX)='''',@COLUMN2 VARCHAR(MAX)=''''SELECT @DECLARE+=''@''+COLUMN_NAME+''''+DATA_TYPE+CASE ISNULL(CAST(CHARACTER_OCTET_LENGTH AS VARCHAR(10)),'''') WHEN '''' THEN '','' WHEN ''-1'' THEN ''(MAX),'' ELSE ''(''+CAST(CHARACTER_OCTET_LENGTH @INTODECLARE+=''@''+COLUMN_NAME+'','',@COLUMN2+=''[''+COLUMN_NAME+''],'' ,@WHERE += ''ISNULL(''+ COLUMN_NAME+'','''''''')=ISNULL(@''+COLUMN_NAME+'','''''''') AND ''FROM INFORMATION_SCHEMA.columnsWHERE TABLE_NAME='''+@TABLENAME+'''SET @DECLARE=LEFT(@DECLARE,LEN(@DECLARE)-1)SET @INTODECLARE=LEFT(@INTODECLARE,LEN(@INTODECLARE)-1)SET @COLUMN2=LEFT(@COLUMN2,LEN(@COLUMN2)-1)SET @WHERE= LEFT(@WHERE,LEN(@WHERE)-3)--*******************判断是否还原当前表的最近⼀次操作*******************DECLARE @SQL_ISLAST VARCHAR(MAX)=''SET NOCOUNT ONDECLARE @maxdate datetimeSELECT @maxdate=max(updatetime) FROM UPDATE_LOG WHERE TableName='''''+@TABLENAME+'''''IF NOT EXISTS(SELECT 1 FROM UPDATE_LOG WHERE UpdateTime=@maxdate AND UPDATEGUID=''''''+@NEWID+'''''')BEGINDECLARE @MAXGUID VARCHAR(50)SELECT @MAXGUID=UPDATEGUID FROM UPDATE_LOG WHERE UpdateTime=@maxdatePRINT ''''此操作并⾮最近⼀次操作,请逐步还原,此表最近⼀次操作的GUID是:''''+@MAXGUIDRETURNEND''--********************还原insert和update操作⽤到的SQL*******************DECLARE @SQL_DELETE VARCHAR(MAX)=''SET ROWCOUNT 1 --设定相同条件下只删除1⾏DECLARE Cursor_ CURSOR FORSELECT ''+@COLUMN2+'' FROM BACKUP_'+@TABLENAME+' WHERE UPDATEGUID= ''''''+@NEWID+'''''' AND UpdateType=''''INSERT''''OPEN Cursor_DECLARE ''+@DECLARE+''FETCH NEXT FROM Cursor_ INTO ''+@INTODECLARE+''WHILE @@FETCH_STATUS=0BEGINDELETE FROM '+@TABLENAME+' WHERE ''+@WHERE+''FETCH NEXT FROM Cursor_ INTO ''+@INTODECLARE+''ENDCLOSE Cursor_DEALLOCATE Cursor_SET ROWCOUNT 0''--*********************还原delete和update操作⽤到的SQL*******************DECLARE @SQL_INSERT VARCHAR(MAX)=''INSERT INTO '+@TABLENAME+' SELECT ''+@COLUMN1+'' FROM BACKUP_'+@TABLENAME+' WHERE UPDATEGUID=''''''+@NEWID+'''''' AND UpdateType=''''DELETE''''''--*********************还原操作之后把备份表和log表的记录删掉*************DECLARE @SQL_DELGUID VARCHAR(MAX)=''DELETE FROM BACKUP_'+@TABLENAME+' WHERE UPDATEGUID IN(SELECT UPDATEGUID FROM UPDATE_LOG WHERE UpdateTime>=@maxdate AND TableName='''''+@TABLENAME+''''') DELETE FROM UPDATE_LOG WHERE UpdateTime>=@maxdate AND TableName='''''+@TABLENAME+'''''PRINT ''''回滚操作执⾏成功,共恢复 ''+CAST(@ROWCOUNT AS VARCHAR(10))+'' 条记录''''SET NOCOUNT OFF''--*********************执⾏还原操作的SQL**********************************DECLARE @EXECSQL VARCHAR(500)=''DECLARE @SQL VARCHAR(MAX)SELECT @SQL=ROLLBACKSQL FROM UPDATE_LOG WHERE UPDATEGUID=''''''+@NEWID+''''''EXEC(@SQL)''--==============================判断执⾏的哪种操作⽅式=================================DECLARE @DoType VARCHAR(MAX)=''UPDATE''IF NOT EXISTS(SELECT 1 FROM deleted)SET @DoType=''INSERT''IF NOT EXISTS(SELECT 1 FROM inserted)SET @DoType=''DELETE''IF NOT EXISTS(SELECT 1 FROM deleted) AND NOT EXISTS(SELECT 1 FROM inserted)RETURNIF @DoType=''UPDATE''BEGININSERT INTO [dbo].[UPDATE_LOG]SELECT @NEWID,GETDATE(),'''+@TABLENAME+''',''UPDATE'',@SQL_ISLAST+@SQL_DELETE+@SQL_INSERT+@SQL_DELGUID,@EXECSQLRETURNENDIF @DoType=''DELETE''BEGININSERT INTO [dbo].[UPDATE_LOG]SELECT @NEWID,GETDATE(),'''+@TABLENAME+''',''DELETE'',@SQL_ISLAST+@SQL_INSERT+@SQL_DELGUID,@EXECSQLRETURNENDIF @DoType=''INSERT''BEGININSERT INTO [dbo].[UPDATE_LOG]SELECT @NEWID,GETDATE(),'''+@TABLENAME+''',''INSERT'',@SQL_ISLAST+@SQL_DELETE+@SQL_DELGUID,@EXECSQL RETURNENDEND'EXEC (@SQLTR)ENDEND---------------------作者:david-sui来源:CSDN原⽂:https:///suixufeng/article/details/76653074 版权声明:本⽂为博主原创⽂章,转载请附上博⽂链接!。
SqlServer2008误操作数据(delete或者update)后恢复数据(亲测有用)
此教程适用于某张表上的数据被delete语句执行误删除掉,来恢复删除的数据;总的来说,需要一份犯错时间点前的完整备份和现在的事务日志备份(只要库还在,可以此时进行事务日志的备份),记住犯错时间点!用事务日志恢复数据,需要两个必要条件:1,正确的完整数据库的最后一次备份(需要恢复的时间点之前的备份)如果没有数据库完整备份,是不能做事务日志备份的,所以建议创建数据库时,恢复模式一项,应当选择'完整'。
2,正确的即时点即所要恢复到数据的时间点,这个时间点一般选择误操作发生时间往前一点的时间点,所以当误操作发生时,应尽量记下这个时间点,不然可能导致恢复的数据不够准确。
比如,误操作发生于16:00,这个时间点我们可以选择15:59,如果选择的太靠前,比如15:30,那么15:30--15:59这段时间内的数据就不能被恢复了。
下面记录具体的操作步骤:首先新建一个数据库dbtest,注意创建数据库时恢复模式一项选择'完整',在数据库中新建一个Table_1,并插入一些数据,然后对该数据库做一个完整备份。
这个备份,主要是模拟实际工作中对数据库的备份,实际中由于数据库可能很大,所以一般备份是一天或者两天进行一次。
备份成功后,接着再往Table_1中插入几条数据, 模拟在原数据库基础上新增加的数据,然后执行一个sql语句:delete from Table_1,模拟误操作,并记录下时间,比如16:00.误操作发生后,我们要赶紧进行事务日志的备份,我们就是根据此备份来还原数据的。
事务日志备份完后,我们可以新建个数据库dbtest1,然后把之前备份的数据库在新建的数据中进行还原,之所以这么做,是因为用事务日志恢复数据库需要获得数据库的独占访问权,如果在原库上进行恢复,那么这需要对原库停止对外服务,但是这样,可能会导致线上系统不能正常运行,造成非常大的影响,所以我们新建个数据库用作数据的还原,而不影响线上系统的正常进行。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
通过sqlserver日志恢复误删除的数据
如果你已经急的焦头烂额,看到这篇文章的时候,请你换个坐姿,深呼吸几次,静下心来将这篇文章读完,也许你的问题迎刃而解。
我遇到的情况是这样的,网站被植入木马,盗取了我的web.config文件,web.config文件里面的数据库连接字符串没有加密,而我的数据库远程连接又没有做IP限制,黑客通过数据库客户端连上我的数据库后,将所有的表都Delete掉了,所以大家一定要有一个好习惯将数据库连接字符串加密或者对远程访问数据库的IP作限制。
因被黑客Delete掉所有数据的具体时间点我不清楚,所以我就用了一个工具Log Explorer来查看分析数据库日志,看具体是什么时候被Delete掉的(若你已经知道想要还原的时间点,就不用使用此工具啦),至于Log Explorer如何安装使用的,这里就不赘述了,去百度一搜一大堆,安装的时候Client和Server 都选,然后安装中会有一步让你输入数据库的用户名和密码,其他不懂的就疯狂下一步吧。
通过Log Explorer工具我查看到被删除的时间点是:07-10 09:46:29.880,那我一会把数据还原到07-10 09:46:29.879就好咧
下面开始言归正传的进行恢复操作了
1、将数据库日志备份一下,用T-Sql语句
2、因我的数据库每天都有自动完整备份,找一个最近时间的完整备份,来还原一下,这里我不往旧库覆盖了,直接还原成一个新的数据库shua2
用SQL Server Management Studio工具进行界面操作吧,写sql语句还原太复杂了,不会啊。
对着数据库->右击->还原数据库,下图是我在[还原数据库]界面->[常规]选项卡页的填写情况
然后点【选项】选项卡页,注意这一步非常重要哦
点击【不对数据库执行任何操作,不回滚来提交的事务】,然后确定。
如果数据库比较大,这个还原要等很长时间,出去吸几口新鲜空气吧,大功就要告成了。
3、待数据库还原成功后,是这个状态
显示(正在还原...),对着shua2这个数据库右击->任务->还原->还原事务日志。
如上图所填,先填刚开始备份的日志c:\shua_log.bak,然后勾选[还原],最重要的是选择时间点,可惜这个时间点不能选毫秒,所以我就选了29秒,这个时候会还原29.0秒以前的数据,而我的数据是从29.880秒被删除的,所以选29秒妥妥的;为什么我没有选择28秒呢?因为我的数据库每一秒的改变都很大,所以我尽可能的缩小这个时间范围。
1、若您的数据库从来没有完整备份过,就不能用此办法恢复了;
2、在【完整备份->现在】这个时间段内,你进行过数据库日志的较大程度压缩,还原起来恐怕也困难了。