欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SQLServer误操作解决方案

程序员文章站 2022-06-24 11:44:20
SQL Server 误操作解决方案 问题: 经常看到有人误删数据,或者误操作,特别是 UPDATE和 DELETE 的时候没有加 WHERE,然后就扎心了。 人非圣贤孰能无...
SQL Server 误操作解决方案

问题:

经常看到有人误删数据,或者误操作,特别是 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(1,1) PRIMARY KEY NOT NULL,
StuName NVARCHAR(16) NOT NULL
)
EXEC sys.sp_addextendedproperty @name = N'MS_Description', -- sysname
    @value = N'学号', -- sql_variant
    @level0type = N'USER', -- varchar(128)
    @level0name = N'DBO', -- sysname
    @level1type = N'TABLE', -- varchar(128)
    @level1name = N'STUDENT', -- sysname
    @level2type = N'COLUMN', -- varchar(128)
    @level2name = N'StuId' -- sysname
EXEC sys.sp_addextendedproperty @name = N'MS_Description', -- sysname
    @value = N'学生姓名', -- sql_variant
    @level0type = N'USER', -- varchar(128)
    @level0name = N'DBO', -- sysname
    @level1type = N'TABLE', -- varchar(128)
    @level1name = N'STUDENT', -- sysname
    @level2type = N'COLUMN', -- varchar(128)
    @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(1, 1)
                  NOT NULL
                  PRIMARY KEY ,
      STUID INT NOT NULL ,
      SCORE DECIMAL NULL
    );
GO

 /********************插入默认数据****************************/
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( 1, 60 )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( 2, 70 )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( 3, 80 )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( 4, 90 )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( 5, 100 )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( 6, 65 )
INSERT INTO dbo.SCORES( STUID, SCORE )VALUES  ( 7, 78 )

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

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