在本機操作,Debug的時候,一切似乎都在掌控之中。可是提交到服務器之后,一切顯地都無比陌生。因為不熟悉SQL,准確來說就只會點Select,Update,Delete,Insert而已。昨天不小心誤刪了一張數據不多但是不在人工處理范圍內的一張表內的數據。
因為知道SQL Server是有日志這種東西的,事后我表現地無比淡定,在事發一個小時以內。一個小時之后,我發現我無法掌控這一事件了。
上網查找了恢復數據的辦法。有必要啰嗦一下。
問題1:
無論是遠程端還是服務器端,都無法對數據庫(假設數據庫叫Test)進行除‘增刪查改’的其它操作,譬如分離,脫機,還原...錯誤提示是
e.g.1 “無法分離 Test 數據庫 因為它當前正在使用。”
e.g.2 “因為數據庫正在使用,未獲得對數據的排他訪問權,操作異常終止”
反正嘛,就是說你丫不能阻止別人的訪問。可我們就是要這樣做的...只好跟它說拜拜了。
說拜拜的方法就是關掉所有訪問數據庫Test的進程。
createproc killspid (@dbnamevarchar(20))
as
begin
declare@sqlnvarchar(500)
declare@spidint
set@sql='declare getspid cursor for select spid from sysprocesses where dbid=db_id('''+@dbname+''')'
exec(@sql)
open getspid
fetchnextfrom getspid into@spid
while@@fetch_status<>-1
begin
exec('kill '+@spid)
fetchnextfrom getspid into@spid
end
close getspid
deallocate getspid
end
--用法
use master
exec killspid '數據庫名'
PS:
代碼我是這樣理解的,定義一段殺死訪問數據庫進程的存儲過程。寫一段獲取進程ID的代碼,循環殺死每一個進程。最后調用存儲過程。
雖然不了解存儲過程,但是意思就是這樣的吧。
問題2:
沒有備份數據庫,那該如何恢復數據呢
有個軟件叫做Log Explorer 這個東西可以根據數據庫的日志回到過去的任何一個時刻。

Log Explorer for SQL Server
打開log explorer file=>attach log file->選擇服務器和登陸方式->connect->
選擇數據庫->attach->左面對話框中browse->view log->就可以看到log記錄了
點擊“View DDL Commands”里面就有很多drop table 命令
點擊下面的“undo”按鈕是生成表結構的語句(create table ....)
點擊下面的“Salvage”按鈕是生成插入語句的(insert into ...values....)
想恢復的話: 右鍵log記錄 undo transation->選擇保存文件名和路徑->然后打開該文件到查詢分析器里執行
T-sql代碼就可以了
例如 如果log是delete table where ...的話,生成的文件代碼就是insert table ....
log explorer使用的幾個問題
對數據庫做了完全 差異 和日志備份
備份時選用了刪除事務日志中不活動的條目
再用Log explorer打試圖看日志時
提示No log recorders found that match the filter,would you like to view unfiltered data
選擇yes,就看不到剛才的記錄了
如果不選用了刪除事務日志中不活動的條目
再用Log explorer打試圖看日志時,就能看到原來的日志
Log Explorer for SQL Server 是個好東西,但是這根本無法解決我的問題。數據庫在服務器端,學校根本不會讓我安裝一個軟件在服務器上面。而且我證實過,這個軟件必須要在服務器端裝服務器端軟件的。所以,這個對於我來說,是泡湯的。但是不代表這不是一個利器。
最后我用了一個很蛋疼的方法解決了。
1.分離數據庫,備份一個Test;
2.將數據庫附加回去,用自帶的恢復方式恢復到一個很久以前的狀態;
3.將需要的那張表復制到備份的那個數據庫;
4.將備份的那個數據庫掛回去,原數據庫刪了。
這是一個很蛋疼而且碰巧那張表沒被改的方法。
頭一次知道DBA的重要性。
我的方法是一個很偶然的東西,希望大家分享一下真正能解決恢復問題的辦法。當然,每隔一段時間備份是絕對沒有錯的。
方法
另外發現一個比較有技術性的可行的方法
1,如果誤操作之前存在一個全庫備份(或已有多個差異備份或增量備份),首先要做的事就是進進行一次日志備份
(如果為了不讓日志文件變大而置trunc. log on chkpt.選項為1那你就死翹了)
backup log dbName to disk='fileName'
----注意:是日志備份!
2,恢復一個全庫備份,注意需要使用with norecovery,如果還有其他差異或增量備份,則逐個恢復
restore database dbName from disk='fileName' with norecovery
3,恢復最后一個日志備份即剛做的日志備份,指定恢復時間點到誤操作之前的時刻
restore log dbName from disk='fileName'
with stopat='date_time'
完整代碼

----1,如果誤操作之前存在一個全庫備份(或已有多個差異備份或增量備份),首先要做的事就是進進行一次日志備份(如果為了不讓日志文件變大而置trunc. log on chkpt.選項為1那你就死翹了)
backup log dbName to disk='fileName'
----注意:是日志備份!
----2,恢復一個全庫備份,注意需要使用with norecovery,如果還有其他差異或增量備份,則逐個恢復
restore database dbName from disk='fileName' with norecovery
----3,恢復最后一個日志備份即剛做的日志備份,指定恢復時間點到誤操作之前的時刻
restore log dbName from disk='fileName'
with stopat='date_time'
經過驗證,這才叫有技術性!我那純屬“鄧艾的屯‘田’”小孩子過家家。。。
參考的資料:
http://blog.163.com/liushui19860112@126/blog/static/132373046201052841232492/