- 類型:數(shù)據(jù)庫(kù)類大。3.1M語(yǔ)言:英文 評(píng)分:6.6
- 標(biāo)簽:
在本機(jī)操作,Debug的時(shí)候,一切似乎都在掌控之中?墒翘峤坏椒⻊(wù)器之后,一切顯地都無(wú)比陌生。因?yàn)椴皇煜QL,準(zhǔn)確來(lái)說(shuō)就只會(huì)點(diǎn)Select,Update,Delete,Insert而已。昨天不小心誤刪了一張數(shù)據(jù)不多但是不在人工處理范圍內(nèi)的一張表內(nèi)的數(shù)據(jù)。
因?yàn)橹繱QL Server是有日志這種東西的,事后我表現(xiàn)地?zé)o比淡定,在事發(fā)一個(gè)小時(shí)以內(nèi)。一個(gè)小時(shí)之后,我發(fā)現(xiàn)我無(wú)法掌控這一事件了。
上網(wǎng)查找了恢復(fù)數(shù)據(jù)的辦法。有必要啰嗦一下。
問(wèn)題1:
無(wú)論是遠(yuǎn)程端還是服務(wù)器端,都無(wú)法對(duì)數(shù)據(jù)庫(kù)(假設(shè)數(shù)據(jù)庫(kù)叫Test)進(jìn)行除‘增刪查改’的其它操作,譬如分離,脫機(jī),還原...錯(cuò)誤提示是
e.g.1 “無(wú)法分離 Test 數(shù)據(jù)庫(kù) 因?yàn)樗?dāng)前正在使用!
e.g.2 “因?yàn)閿?shù)據(jù)庫(kù)正在使用,未獲得對(duì)數(shù)據(jù)的排他訪問(wèn)權(quán),操作異常終止”
反正嘛,就是說(shuō)你丫不能阻止別人的訪問(wèn)?晌覀兙褪且@樣做的...只好跟它說(shuō)拜拜了。
說(shuō)拜拜的方法就是關(guān)掉所有訪問(wèn)數(shù)據(jù)庫(kù)Test的進(jìn)程。
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 '數(shù)據(jù)庫(kù)名'
PS:
代碼我是這樣理解的,定義一段殺死訪問(wèn)數(shù)據(jù)庫(kù)進(jìn)程的存儲(chǔ)過(guò)程。寫一段獲取進(jìn)程ID的代碼,循環(huán)殺死每一個(gè)進(jìn)程。最后調(diào)用存儲(chǔ)過(guò)程。
雖然不了解存儲(chǔ)過(guò)程,但是意思就是這樣的吧。
問(wèn)題2:
沒(méi)有備份數(shù)據(jù)庫(kù),那該如何恢復(fù)數(shù)據(jù)呢
有個(gè)軟件叫做Log Explorer 這個(gè)東西可以根據(jù)數(shù)據(jù)庫(kù)的日志回到過(guò)去的任何一個(gè)時(shí)刻。
Log Explorer for SQL Server 打開(kāi)log explorer file=>attach log file->選擇服務(wù)器和登陸方式->connect-> 選擇數(shù)據(jù)庫(kù)->attach->左面對(duì)話框中browse->view log->就可以看到log記錄了 點(diǎn)擊“View DDL Commands”里面就有很多drop table 命令 點(diǎn)擊下面的“undo”按鈕是生成表結(jié)構(gòu)的語(yǔ)句(create table ....) 點(diǎn)擊下面的“Salvage”按鈕是生成插入語(yǔ)句的(insert into ...values....) 想恢復(fù)的話: 右鍵log記錄 undo transation->選擇保存文件名和路徑->然后打開(kāi)該文件到查詢分析器里執(zhí)行 T-sql代碼就可以了 例如 如果log是delete table where ...的話,生成的文件代碼就是insert table .... log explorer使用的幾個(gè)問(wèn)題 對(duì)數(shù)據(jù)庫(kù)做了完全 差異 和日志備份 備份時(shí)選用了刪除事務(wù)日志中不活動(dòng)的條目 再用Log explorer打試圖看日志時(shí) 提示No log recorders found that match the filter,would you like to view unfiltered data 選擇yes,就看不到剛才的記錄了 如果不選用了刪除事務(wù)日志中不活動(dòng)的條目 再用Log explorer打試圖看日志時(shí),就能看到原來(lái)的日志
Log Explorer for SQL Server 是個(gè)好東西,但是這根本無(wú)法解決我的問(wèn)題。數(shù)據(jù)庫(kù)在服務(wù)器端,學(xué)校根本不會(huì)讓我安裝一個(gè)軟件在服務(wù)器上面。而且我證實(shí)過(guò),這個(gè)軟件必須要在服務(wù)器端裝服務(wù)器端軟件的。所以,這個(gè)對(duì)于我來(lái)說(shuō),是泡湯的。但是不代表這不是一個(gè)利器。
最后我用了一個(gè)很蛋疼的方法解決了。
1.分離數(shù)據(jù)庫(kù),備份一個(gè)Test;
2.將數(shù)據(jù)庫(kù)附加回去,用自帶的恢復(fù)方式恢復(fù)到一個(gè)很久以前的狀態(tài);
3.將需要的那張表復(fù)制到備份的那個(gè)數(shù)據(jù)庫(kù);
4.將備份的那個(gè)數(shù)據(jù)庫(kù)掛回去,原數(shù)據(jù)庫(kù)刪了。
這是一個(gè)很蛋疼而且碰巧那張表沒(méi)被改的方法。
頭一次知道DBA的重要性。
我的方法是一個(gè)很偶然的東西,希望大家分享一下真正能解決恢復(fù)問(wèn)題的辦法。當(dāng)然,每隔一段時(shí)間備份是絕對(duì)沒(méi)有錯(cuò)的。
方法
另外發(fā)現(xiàn)一個(gè)比較有技術(shù)性的可行的方法
1,如果誤操作之前存在一個(gè)全庫(kù)備份(或已有多個(gè)差異備份或增量備份),首先要做的事就是進(jìn)進(jìn)行一次日志備份
。ㄈ绻麨榱瞬蛔屓罩疚募兇蠖胻runc. log on chkpt.選項(xiàng)為1那你就死翹了)
backup log dbName to disk='fileName' ----注意:是日志備份!
2,恢復(fù)一個(gè)全庫(kù)備份,注意需要使用with norecovery,如果還有其他差異或增量備份,則逐個(gè)恢復(fù)
restore database dbName from disk='fileName' with norecovery
3,恢復(fù)最后一個(gè)日志備份即剛做的日志備份,指定恢復(fù)時(shí)間點(diǎn)到誤操作之前的時(shí)刻
restore log dbName from disk='fileName' with stopat='date_time'
完整代碼
----1,如果誤操作之前存在一個(gè)全庫(kù)備份(或已有多個(gè)差異備份或增量備份),首先要做的事就是進(jìn)進(jìn)行一次日志備份(如果為了不讓日志文件變大而置trunc. log on chkpt.選項(xiàng)為1那你就死翹了) backup log dbName to disk='fileName' ----注意:是日志備份! ----2,恢復(fù)一個(gè)全庫(kù)備份,注意需要使用with norecovery,如果還有其他差異或增量備份,則逐個(gè)恢復(fù) restore database dbName from disk='fileName' with norecovery ----3,恢復(fù)最后一個(gè)日志備份即剛做的日志備份,指定恢復(fù)時(shí)間點(diǎn)到誤操作之前的時(shí)刻 restore log dbName from disk='fileName' with stopat='date_time'