SQLServer-2008以上误操作数据库恢复方法

合集下载

SQL Server 2008恢复数据

SQL Server 2008恢复数据

SQL Server 2008恢复数据恢复数据,就是让数据库根据备份回到备份时的状态。

当恢复数据库时,SQL Server 会自动将备份文件中的数据全部复制到数据库,并回滚任何未完成的事务,以保证数据库中的数据的完整性。

下面将使用SQL Server Management Studio工具将前面所备份的数据库进行恢复数据库的操作步骤如下:(1)打开SQL Server Management Studio窗口,在【对象资源管理器】中,展开数据库,右击【SMSstudent】数据库,执行【任务】|【还原】|【数据库】命令,如图10-26所示。

图10-26 执行【还原数据库】命令(2)在【还原数据库】对话框中,启用【源设备】单选按钮,单击按钮,将弹出【指定备份】对话框。

给图()在该对话框中,选择【备份介质】下拉列表中的【备份设备】选项,再单击【添加】按钮,选择之前创建的Most备份设备,如图10-27所示。

图10-27选择备份设备(3)指定备份完成后单击【确定】按钮,返回到【还原数据库】窗口,在【选择用于还原的备份集】列表中显示“完整”和“事务日志”备份,可这使数据库恢复到最近一次备份的正确状态,如图10-28所示。

图10-28 还原数据库的【常规】页面(4)在【选项】页面选择RESTORE WITH RECOVERY选项,如图10-29所示。

图10-29 还原数据库的【选项】页面(5)设置完成后,单击【确定】按钮开始恢复,恢复完成后将弹出还原成功的对话框。

如果还需要恢复别的备份文件,需要选择RESTORE WITH NORECOVERY选项,恢复完成后,数据库会显示处于正在还原状态,无法进行操作,必须到最后一个备份还原为止,如图10-30所示。

图10-30 数据库的还原状态当执行还原最后一个备份时候,必须选择RESTORE WITH RECOVERY选项,否则数据库将一直处于还原状态。

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被误删除的数据

恢复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],。

SQLServer2008数据库备份还原和数据恢复图文教程

SQLServer2008数据库备份还原和数据恢复图文教程

SQLServer2008数据库备份还原和数据恢复图⽂教程在完整恢复模式或⼤容量⽇志恢复模式下,必须先备份活动事务⽇志(称为⽇志尾部),然后才能在SQLServerManagementStudio中还原数据库。

有关详细信息,请参阅如何备份事务⽇志(SQLServerManagementStudio)。

若要还原已加密的数据库,您必须有权访问⽤于加密数据库的证书或⾮对称密钥。

如果没有证书或⾮对称密钥,数据库将⽆法还原。

认识数据库备份和事务⽇志备份数据库备份与⽇志备份是数据库维护的⽇常⼯作,备份的⽬的是在于当数据库出现故障或者遭到破坏时可以根据备份的数据库及事务⽇志⽂件还原到最近的时间点将损失降到最低点。

数据库备份数据库备份可以⼿动备份和语句备份⼀.⼿动备份数据库1.⿏标右键选择你要进⾏备份的数据库-任务-备份可以在常规选项页⾯你可以选择备份类型是进⾏完整数据库备份还是差异数据库备份2.点击添加选项,选择数据库⽂件的存放路径注意⽂件名记得加后缀.bak,便于恢复时的查找3.你还可以在选项页⾯是追加到现有的备份集,还是覆盖所有的现有备份集,还可以选择备份验证完整性(建议选择),还可以选择是否压缩备份等。

⼆.语句备份数据库use master goBACKUP DATABASE [test] TO DISK = N'D:\Microsoft sql server\MSSQL10.MSSQLSERVER\MSSQL\Backup\test.bak' WITH NOFORMAT, NOINIT, NAME = N'test-完整数据库备份', SKIP, NOREWIND, NOUNLOAD, STATS = 10GO数据库⽇志备份⾸先需要注意,数据库⽇志的备份是基于数据库完整备份,也就是说你备份数据库⽇志之前你⾸先要先对数据库进⾏⼀次完整的备份,因为之间会涉及到坚持到检查点lsn,这也是本⽂接下来要讲的重点。

SQLSERVER 数据恢复

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)还原完整备份选择还原【文件和文件组】,在【常规】中选择完整备份的数据库,先要还原完整备份,选择最近的那次,由于日志备份的特性,只认最后一次备份,所以要选择最新的那次,否则还原不了。

SQLServer2008数据备份与还原(操作篇)

SQLServer2008数据备份与还原(操作篇)

SQLServer2008数据备份与还原(操作篇)
⼀、数据库的备份
1. 选择要备份的数据库“B”,点击⿏标右键→任务→备份
2. 在打开的“备份数据库 —B”对话框中,先点击删除,然后点击“添加”
3. 在弹出的“选择备份⽬标”对话框中
4. 择好备份的路径(如“D:\数据备份”),⽂件类型选择“所有⽂件”,“⽂件名”那个位置填写上您要备份的数据库的名字(最好在您备份的
数据库的名字后⾯加上⽇期,以⽅便以后查找),之后连续点击“确定”按钮即可完成数据库的备份操作
⼆、数据库的还原
1. 选择您要还原的数据库“B”,点击⿏标右键→任务→还原→数据库
2. 在出现的“还原数据库 — school_web_db”对话框中选择“源设备”,然后点击后⾯的“…”按钮
3. 在出现的“指定备份”对话框中,点击“添加”按钮
4. 找到数据库备份的路径,选择您所要还原的数据库“B”(注意:⽂件类型选择所有⽂件),然后连续“两次”点击“确定”按钮
5. 在出现的“还原数据库 — B”对话框中,勾选上“选择⽤于还原的备份集”下的数据库前的复选框
6. 然后选择“选项”,勾选上“覆盖现有数据库”
三、还原数据库问题解决⽅案
在还原数据库“B”时,有时会遇见下图中的问题“因为数据库正在使⽤,所以⽆法获得对数据库的独占访问权”
此时我们可以按照以下步骤解决此问题
1. 右键数据库“B”,然后选择“属性”,在出现的“数据库属性 — B ”对话框中,选择“选项”,在“其他选项”下的“状态”中找到“限制访问”。


择“SINGLE_USER”,点击“确定”按钮
2. 按照正常还原数据库的步骤,还原数据库。

SQLServer2008备份和恢复及作业

SQLServer2008备份和恢复及作业

目标:1.理解SQLServer2008R2的备份方式(完整,差异,日志备份)和恢复模式;2.能够进行完整备份,差异备份操作,事务日志备份,并进行恢复操作;3.使用维护计划实现日常的数据库备份操作;一、SQLServer2008R2的备份恢复1、恢复模式类型所有的数据库都可以设置为三个不同的恢复模式:简单(simple),完全(full),大容量日志(Bulk-Logged).A完全恢复模式完全恢复模式是默认的恢复模式。

在完全恢复模式下,需要手工的对事务日志进行管理。

使用完全恢复模式的优点是可以恢复到数据库失败或者指定的时间点上。

缺点则是,如果没有进行管理的话,事务日志将会快速增长,消耗磁盘空间。

要清除事务日志,只能通过备份事务日志,或者切换至简单模式。

B简单恢复模式与完全恢复模式不同的是,在简单恢复模式下,在检查点发生时(checkpoint),当前已被提交的事务日志将会被清除。

因此,在简单恢复模式下,容易造成数据丢失,因为无法将数据库恢复到失败的那一刻。

需要注意的是,虽然在简单恢复模式下,系统会自动定期清除日志,但这并不意味着事务日志文件不会增长。

例如,如果执行一个批量插入操作时,SQL SERVER会将该相关操作当成一个事务,期间产生的日志量在极端情况下,还是非常可观的。

C大容量日志恢复模式大容量日志恢复模式与完全恢复模式非常相似,但与完全恢复模式不同的是,批量操作将会尽量被最少记录。

批量操作有以下几种类型:1. 批量导入数据,例如使用BCP(Bulk Copy Import) , BULK INSERT命令,或者是在BULK 使用OPENROWSET命令;2. 大对象操作(LOB),例如在TEXT, NTEXT, IMAGE 列上使用WRITETEXT 或者UPDATETEXT;3. SELECT INTO 字句;4. CREATE INDEX, ALTER INDEX, ALTER INDEX REBUILD, DBCC REINDEX在完全恢复模式下,上述操作产生的日志将会是非常大的。

SQLServer 2008以上误操作数据库恢复方法

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))来说,完整恢复模式产生的日志会大,但是在出现问题的时候,就会觉得这些都不算什么了。

并且我也想不到任何理由对于正式环境不使用完整恢复模式。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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_desc
2.FROM sys.databases
3.WHERE name='AdventureWorks'
结果如下:
确保数据库的恢复模式最起码不能为【简单】。

至于如何修改成完整模式,我觉得这些应该没必要多说了。

切记,对于任何重要环境,不仅仅是客户正式环境(俗称生产环境),都强烈建议使用【完整恢复模式】,虽然对于另外两种(大容量日志(BULK_LOGGED)、简单(SIMPLE))来说,完整恢复模式产生的日志会大,但是在出现问题的时候,就会觉得这些都不算什么了。

并且我也想不到任何理由对于正式环境不使用完整恢复模式。

只要管理得当,完整恢复模式的日志也不会太变态。

(2)、这里其实隐含另外一步,曾经做过最少一次的完整备份。

因为所有类型的备份都基于完整备份,如果没有最少一次完整备份,其他类型的备份都是多余的,所以在这里强调一下,在创建完一个新数据库之后,强烈建议甚至强制做一次完整备份。

[sql]view plaincopyprint?
1.SELECT database_name,recovery_model,name
2.FROM msdb.dbo.backupset
使用上面的语句粗略可以看到有那些数据库做过备份,由于测试,所以做了几次备份,可以看到我这个时间点已经做了备份了。

(3)、确保别人不再连接数据库,然后做一次日志尾部备份:
首先先创建一点数据:
[sql]view plaincopyprint?
1./*
2.由于tempdb永远为简单恢复模式,所以不适合做案例。

3.这里使用微软的示例数据库AdventureWorks
4.*/
E AdventureWorks
6.GO
7.IF OBJECT_ID('testRestore') IS NOT NULL
8.DROP TABLE testRestore
9.GO
10.CREATE TABLE testRestore
11.(
12.id INT IDENTITY(1, 1) ,
VARCHAR(50)
14.);
15.--插入测试数据:
16.INSERT INTO testRestore(Name)
17.SELECT'test1'
18.UNION ALL
19.SELECT'test2'
20.UNION ALL
21.SELECT'test3'
22.UNION ALL
23.SELECT'test4'
24.UNION ALL
25.SELECT'test5'
26.UNION ALL
27.SELECT'test6'
28.UNION ALL
29.SELECT'test7'
30.UNION ALL
31.SELECT'test8'
32.SELECT* FROM testRestore
检查一下结果:
然后来做个删除操作,为了定位是啥时候发生的,我加了一个waitfor命令,让它在某个时间发生,这样恢复的时候就有准确性:
[sql]view plaincopyprint?
E AdventureWorks
2.GO
3.WAITFOR TIME'21:45'
4.DELETE FROM dbo.testRestore
现在来看看数据:
[sql]view plaincopyprint?
E AdventureWorks
2.GO
3.SELECT* FROM dbo.testRestore
到这一步,灾难出现了。

但是切记要冷静。

下面就是本文的重点开始,做一次日志备份,最重要是选择【备份日志尾部】
然后在【选项】页选择:除【事务日志】除,其他红框包裹的地方为强烈建议勾选的地方。

并且保证数据库不要有别人在连接,因为备份日志尾部会使数据库处于还原状态,拒绝其他会话的连接,如果不断开其他连接,是备份不了的。

然后按确定,当然,可以使用上方的【脚本】来生成语句:
[sql]view plaincopyprint?
E Master
2.GO
3.BACKUP LOG [AdventureWorks] TO DISK = N'E:\Adven
tureWorks.bak'WITH NO_TRUNCATE , NOFORMAT, NOINI T, NAME= N'AdventureWorks-事务日志备份
', SKIP, NOREWIND, NOUNLOAD, NORECOVERY , COMPRE SSION, STATS = 10, CHECKSUM
4.GO
5.declare@backupSetId as int
6.select@backupSetId = position from msdb..backupset
where database_name=N'AdventureWorks'and backup_se
t_id=(select max(backup_set_id) from msdb..backupset
where database_name=N'AdventureWorks')
7.if @backupSetId is null begin raiserror(N'验证失败。

找不到数据库“AdventureWorks”的备份信息。

', 16, 1) end
8.RESTORE VERIFYONLY FROM DISK = N'E:\AdventureWork
s.bak'WITH FILE = @backupSetId, NOUNLOAD, N
OREWIND
9.GO
此时,数据库会处于【正在还原】的状态
如果发现备份不了可以用下面语句查看,并把spid杀掉:
[sql]view plaincopyprint?
1.SELECT* FROM sys.sysprocesses WHERE dbid=DB_ID('
AdventureWorks')
执行结果:
然后kill掉。

接着继续备份。

然后进行还原,如图:
先要还原完整备份,选择最近的那次,由于日志备份的特性(以后其他文章再说),只认最后一次备份,所以要选择最新的那次,否则还原不了。

这里又有一个注意事项,记得选择:
接着还原日志文件,这是最最重要的一步:
然后:
由于实验的时候出了点问题,后面重做了,所以时间选择到22:19分,我是在22:20分删除数据的。

这里不用太在意,只要把时间点指定到你误删除的时间之前即可。

而由于日志尾部备份都是最后一个备份文件,所以这里选则红框部分即可:
现在再检查一下:
可以看到,数据已经还原成功。

总结:
平时不做备份,出问题来喊急,这是苟有自取,还有一些脑袋发热的人喜欢看到ldf很大就直接删除,那以后出问题就别怪微软了。

本文中的方法看上去有点繁琐,但是实操几次就觉得好了,但是步骤建议严格按照上面说的,因为一旦操作错误,就很麻烦,此时再次强调——冷静冷静再冷静!!!!!!
这种方法有几个缺点:
1、如果你发现误操作以后还有很多人做了操作,那么你还原成功后,别人的操作就会冲掉,所以发生误操作后,要马上停止别人对数据库的操作。

2、这个方法要对数据库独占,所以你想偷偷恢复是不行的了。

勇敢承认错误吧。

对于核心数据表,还是要先做好预防操作,可以看:SQLServer恢复表级数据。

(注:可编辑下载,若有不当之处,请指正,谢谢!)。

相关文档
最新文档