sql service ---- update和delete 誤操作數據 ---- 恢復數據
原文出處:http://blog.csdn.net/dba_huangzj/article/details/8491327
問題:
經常看到有人誤刪數據,或者誤操作,特別是update和delete的時候沒有加where,然後就喊爹喊娘了。人非聖賢孰能無過,做錯可以理解,但不能縱容,這個以後再說,現在先來解決問題。
遇到這種情況,一般都是沒有做備份,不然也不會來發問了。首先要冷靜,否則會有更大的災難。直到你放棄。
解決方法:
對於這類問題,主要是找回誤操作之前的數據,在2008之前,有個很出名的工具Log Exploer,聽說還挺好用的,這個網上大把教程,這裏就不多說了。但是唯一遺憾的是,不支持2008及更高版本,這時除了其他第三方工具,那麽最常用的就是本文提到的方法——日誌尾部備份。本文實驗環境2008R2,對於2008及其以上版本可以使用這個方法,其實2005也可以,2000很少用,沒試過,只是2008之前可以使用Log Exploer,所以就沒必要用這種方法。
下面圖文並茂講解操作方法,至於原理,不屬於本文範圍,而且我相信真遇到誤操作的時候,估計沒人會看原理了。
步驟:
(1)、檢查數據庫的恢復模式,如圖:
或者使用腳本檢查:
[sql] view plain copy print?- SELECT recovery_model,recovery_model_desc
- FROM sys.databases
- WHERE name =‘AdventureWorks‘
結果如下:
確保數據庫的恢復模式最起碼不能為【簡單】。至於如何修改成完整模式,我覺得這些應該沒必要多說了。
切記,對於任何重要環境,不僅僅是客戶正式環境(俗稱生產環境),都強烈建議使用【完整恢復模式】,雖然對於另外兩種(大容量日誌(BULK_LOGGED)、簡單(SIMPLE))來說,完整恢復模式產生的日誌會大,但是在出現問題的時候,就會覺得這些都不算什麽了。並且我也想不到任何理由對於正式環境不使用完整恢復模式。只要管理得當,完整恢復模式的日誌也不會太變態。
(2)、這裏其實隱含另外一步,曾經做過最少一次的完整備份。因為所有類型的備份都基於完整備份,如果沒有最少一次完整備份,其他類型的備份都是多余的,所以在這裏強調一下,在創建完一個新數據庫之後,強烈建議甚至強制做一次完整備份。
[sql] view plain copy print?- SELECT database_name,recovery_model,name
- FROM msdb.dbo.backupset
使用上面的語句粗略可以看到有那些數據庫做過備份,由於測試,所以做了幾次備份,可以看到我這個時間點已經做了備份了。
(3)、確保別人不再連接數據庫,然後做一次日誌尾部備份:
首先先創建一點數據:
[sql] view plain copy print?- /*
- 由於tempdb永遠為簡單恢復模式,所以不適合做案例。
- 這裏使用微軟的示例數據庫AdventureWorks
- */
- USE AdventureWorks
- GO
- IF OBJECT_ID(‘testRestore‘) IS NOT NULL
- DROP TABLE testRestore
- GO
- CREATE TABLE testRestore
- (
- id INT IDENTITY(1, 1) ,
- NAME VARCHAR(50)
- );
- --插入測試數據:
- INSERT INTO testRestore(Name)
- SELECT ‘test1‘
- UNION ALL
- SELECT ‘test2‘
- UNION ALL
- SELECT ‘test3‘
- UNION ALL
- SELECT ‘test4‘
- UNION ALL
- SELECT ‘test5‘
- UNION ALL
- SELECT ‘test6‘
- UNION ALL
- SELECT ‘test7‘
- UNION ALL
- SELECT ‘test8‘
- SELECT * FROM testRestore
檢查一下結果:
然後來做個刪除操作,為了定位是啥時候發生的,我加了一個waitfor命令,讓它在某個時間發生,這樣恢復的時候就有準確性:
[sql] view plain copy print?- USE AdventureWorks
- GO
- WAITFOR TIME ‘21:45‘
- DELETE FROM dbo.testRestore
現在來看看數據:
[sql] view plain copy print?- USE AdventureWorks
- GO
- SELECT * FROM dbo.testRestore
到這一步,災難出現了。但是切記要冷靜。
下面就是本文的重點開始,做一次日誌備份,最重要是選擇【備份日誌尾部】
然後在【選項】頁選擇:除【事務日誌】除,其他紅框包裹的地方為強烈建議勾選的地方。並且保證數據庫不要有別人在連接,因為備份日誌尾部會使數據庫處於還原狀態,拒絕其他會話的連接,如果不斷開其他連接,是備份不了的。
然後按確定,當然,可以使用上方的【腳本】來生成語句:
[sql] view plain copy print?
- USE Master
- GO
- BACKUP LOG [AdventureWorks] TO DISK = N‘E:\AdventureWorks.bak‘ WITH NO_TRUNCATE , NOFORMAT, NOINIT, NAME = N‘AdventureWorks-事務日誌 備份‘, SKIP, NOREWIND, NOUNLOAD, NORECOVERY , COMPRESSION, STATS = 10, CHECKSUM
- GO
- declare @backupSetId as int
- select @backupSetId = position from msdb..backupset where database_name=N‘AdventureWorks‘ and backup_set_id=(select max(backup_set_id) from msdb..backupset where database_name=N‘AdventureWorks‘ )
- if @backupSetId is null begin raiserror(N‘驗證失敗。找不到數據庫“AdventureWorks”的備份信息。‘, 16, 1) end
- RESTORE VERIFYONLY FROM DISK = N‘E:\AdventureWorks.bak‘ WITH FILE = @backupSetId, NOUNLOAD, NOREWIND
- GO
此時,數據庫會處於【正在還原】的狀態
如果發現備份不了可以用下面語句查看,並把spid殺掉:
[sql] view plain copy print?
- SELECT * FROM sys.sysprocesses WHERE dbid=DB_ID(‘AdventureWorks‘)
執行結果:
然後kill掉。
接著繼續備份。
然後進行還原,如圖:
先要還原完整備份,選擇最近的那次,由於日誌備份的特性(以後其他文章再說),只認最後一次備份,所以要選擇最新的那次,否則還原不了。
這裏又有一個註意事項,記得選擇:
接著還原日誌文件,這是最最重要的一步:
然後:
由於實驗的時候出了點問題,後面重做了,所以時間選擇到22:19分,我是在22:20分刪除數據的。這裏不用太在意,只要把時間點指定到你誤刪除的時間之前即可。而由於日誌尾部備份都是最後一個備份文件,所以這裏選則紅框部分即可:
現在再檢查一下:
可以看到,數據已經還原成功。
sql service ---- update和delete 誤操作數據 ---- 恢復數據