天天看点

SQL Server 误操作解决方案SQL Server 误操作解决方案

SQL Server 误操作解决方案

原文出处:http://blog.csdn.net/dba_huangzj/article/details/8491327

问题:

经常看到有人误删数据,或者误操作,特别是 UPDATE和 DELETE 的时候没有加 WHERE,然后就扎心了。

人非圣贤孰能无过,做错可以理解,但不能纵容,这个以后再说,现在先来解决问题。

遇到这种情况,一般都是没有做备份,不然也不会来发问了。首先要 冷静!!!,否则会有更大的灾难。直到你放弃。话不多说,请看下文。

/*****************

步骤:

1、将数据库属性》选项》恢复模式,设置为完整。可使用下面语句查询当前恢复模式

SELECT recovery_model,recovery_model_desc

FROM sys.databases

WHERE name =’DataBaseRecover’

确保数据库的恢复模式位“完整”模式

2、做1次“完整”备份。使用以下语句可查询备份信息

SELECT database_name,recovery_model,name,backup_finish_date

FROM msdb.dbo.backupset

3、插入一些数据。

4、删除数据。
        USE DataBaseRecover  
        GO  
        WAITFOR TIME '10:29'  
        DELETE FROM dbo.STUDENT  

        SELECT * FROM dbo.STUDENT           
        为了定位是啥时候发生的,加了一个waitfor命令,让它在某个时间发生,这样恢复的时候就有准确性。

5、再做1“完整”备份。

6、断开数据库所有连接

7、做一次 “日志尾部备份” !!!!!!
        (1)使用可视化工具备份
            右击数据库》任务》备份》
            常规:【备份类型:事务日志】
            选项:【可靠性:√ 完成后验证备份;√ 写入介质前检查校验】
                【事务日志:√ 备份日志尾部】
            点击确定。

        (2)使用语句备份
            USE Master  
            GO  
            BACKUP LOG [DataBaseRecover] TO  DISK = N'F:\DataBaseRecover_TransLog_Backup.bak' WITH  NO_TRUNCATE , NOFORMAT, NOINIT,  NAME = N'DataBaseRecover-事务日志 备份', SKIP, NOREWIND, NOUNLOAD,  NORECOVERY , COMPRESSION,  STATS = 10, CHECKSUM  
            GO  
            declare @backupSetId as int  
            select @backupSetId = position from msdb..backupset where database_name=N'DataBaseRecover' and backup_set_id=(select max(backup_set_id) from msdb..backupset where database_name=N'DataBaseRecover' )  
            if @backupSetId is null begin raiserror(N'验证失败。找不到数据库“AdventureWorks”的备份信息。', 16, 1) end  
            RESTORE VERIFYONLY FROM  DISK = N'E:\DataBaseRecover_TransLog_Backup.bak' WITH  FILE = @backupSetId,  NOUNLOAD,  NOREWIND  
            GO  

            如果备份不了,使用以下语句查看,并把spid杀掉
            SELECT  * FROM sys.sysprocesses WHERE dbid=DB_ID('DataBaseRecover')  
            然后kill掉。接着继续备份。

8、此时,数据库处于“正在还原“状态

9、开始还原
    (1)还原文件和文件组(数据库):
            常规》选择最近的一次“完整”备份
            选项》恢复状态:选择“不对数据库执行任何操作”
    (2)还原“事务日志”
            常规》时间点:把时间点指定到你误删除的时间之前
                        (这里我的删除操作是10:29:00,我这里还原时选择的是10:28:00)
            选项》恢复状态:选择“回滚未提交的事务”

10、完成。检查数据是否恢复
           

总结:

平时尽量做备份,别等到出问题来喊急,数据无价,操作需谨慎,那以后出问题就别怪微软了。

本文中的方法看上去有点繁琐,但是实操几次就觉得好了,但是步骤建议严格按照上面说的,因为一旦操作错误,就很麻烦,此时再次强调——冷静冷静再冷静!!!!!!

这种方法有几个缺点:

1、 如果你发现误操作以后还有很多人做了操作,那么你还原成功后,别人的操作就会冲掉,所以发生误操作后,要马上停止别人对数据库的操作。

2、 这个方法要对数据库独占,所以你想偷偷恢复是不行的了。勇敢承认错误吧。

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

******************/

本文作者测试用例:

/***************************
准备:
    创建测试数据库,数据表,插入默认数据
****************************/

/*******************创建数据库****************************/
IF db_id('DataBaseRecover') IS NOT NULL
    PRINT db_id('DataBaseRecover')
    DROP DATABASE DataBaseRecover
GO

CREATE DATABASE DataBaseRecover
GO
USE DataBaseRecover
GO

/********************创建学生表***************************/
CREATE TABLE STUDENT(
StuId INT IDENTITY(,) PRIMARY KEY NOT NULL,
StuName NVARCHAR() NOT NULL
)
EXEC sys.sp_addextendedproperty @name = N'MS_Description', -- sysname
    @value = N'学号', -- sql_variant
    @level0type = N'USER', -- varchar()
    @level0name = N'DBO', -- sysname
    @level1type = N'TABLE', -- varchar()
    @level1name = N'STUDENT', -- sysname
    @level2type = N'COLUMN', -- varchar()
    @level2name = N'StuId' -- sysname
EXEC sys.sp_addextendedproperty @name = N'MS_Description', -- sysname
    @value = N'学生姓名', -- sql_variant
    @level0type = N'USER', -- varchar()
    @level0name = N'DBO', -- sysname
    @level1type = N'TABLE', -- varchar()
    @level1name = N'STUDENT', -- sysname
    @level2type = N'COLUMN', -- varchar()
    @level2name = N'StuName' -- sysname

 /********************插入默认数据****************************/
INSERT INTO DBO.STUDENT( StuName )VALUES  ( N'用户001' )
INSERT INTO DBO.STUDENT( StuName )VALUES  ( N'用户002' )
INSERT INTO DBO.STUDENT( StuName )VALUES  ( N'用户003' )
INSERT INTO DBO.STUDENT( StuName )VALUES  ( N'用户004' )
INSERT INTO DBO.STUDENT( StuName )VALUES  ( N'用户005' )
INSERT INTO DBO.STUDENT( StuName )VALUES  ( N'用户006' )
INSERT INTO DBO.STUDENT( StuName )VALUES  ( N'用户007' )
INSERT INTO DBO.STUDENT( StuName )VALUES  ( N'用户008' )
INSERT INTO DBO.STUDENT( StuName )VALUES  ( N'用户009' )
INSERT INTO DBO.STUDENT( StuName )VALUES  ( N'用户010' )



/*********************创建得分表*******************************/
IF OBJECT_ID('SCORES','U') IS NOT NULL
    DROP TABLE SCORES
GO

CREATE TABLE SCORES
    (
      SCOREID INT IDENTITY(, )
                  NOT NULL
                  PRIMARY KEY ,
      STUID INT NOT NULL ,
      SCORE DECIMAL NULL
    );
GO

 /********************插入默认数据****************************/
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( ,  )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( ,  )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( ,  )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( ,  )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( ,  )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( ,  )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( ,  )

/**查询:学生表*/
SELECT STUID,StuName FROM dbo.STUDENT

/**查询:得分表*/
SELECT SCOREID,STUID,SCORE FROM dbo.SCORES
           

继续阅读