天天看點

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
           

繼續閱讀