SQLServer中update没带where的回滚操作(Update或者Delete
误操。。。
SQLServer中update没带where的回滚操作(Update或者Delete误操作恢复⽅法)
SQLServer 2008以上误操作数据库恢复⽅法——⽇志尾部备份
问题:
经常看到有⼈误删数据,或者误操作,特别是update和delete的时候没有加where,然后就喊爹喊娘了。⼈⾮圣贤孰能⽆过,做错可以理解,但不能纵容,这个以后再说,现在先来解决问题。
遇到这种情况,要分两种情况来分别对待:
⼀:数据库曾经做过完整备份的
⼆:数据库从未做过完整备份的
--------------------------------------------------------------------------------------------------------------------------
⼀:数据库曾经做过完整备份的
--------------------------------------------------------------------------------------------------------------------------
⼆:数据库从未做过完整备份的
如果都是没有做备份,请按下⽅⽅法来解决。⾸先要冷静,否则会有更⼤的灾难。直到你放弃。
解决⽅法:
对于这类问题,主要是回误操作之前的数据,在2008之前,有个很出名的⼯具Log Exploer,听说还挺好⽤的,这个⽹上⼤把教程,这⾥就不多说了。但是唯⼀遗憾的是,不⽀持2008及更⾼版本,这时除了其他第三⽅⼯具,那么最常⽤的就是本⽂提到的⽅法——⽇志尾部备份。本⽂实验环境2008R2,对于2008及其以上版本可以使⽤这个⽅法,其实2005也可以,2000很少⽤,没试过,只是2008之前可以使⽤Log Exploer,所以就没必要⽤这种⽅法。
下⾯图⽂并茂讲解操作⽅法,⾄于原理,不属于本⽂范围,⽽且我相信真遇到误操作的时候,估计没⼈会看原理了。
1)、检查数据库的恢复模式,如图:
或者使⽤脚本检查:
SELECT recovery_model,recovery_model_desc
FROM sys.databases
WHERE name ='AdventureWorks'
结果如下:
确保数据库的恢复模式最起码不能为【简单】。⾄于如何修改成完整模式,我觉得这些应该没必要多说了。
切记,对于任何重要环境,不仅仅是客户正式环境(俗称⽣产环境),都强烈建议使⽤【完整恢复模式】,虽然对于另外两种(⼤容量⽇志(BULK_LOGGED)、简单(SIMPLE))来说,完整恢复模式产⽣的⽇志会⼤,但是在出现问题的时候,就会觉得这些都不算什么了。并且我也想不到任何理由对于正式环境不使⽤完整恢复模式。只要管理得当,完整恢复模式的⽇志也不会太变态。
(2)、这⾥其实隐含另外⼀步,曾经做过最少⼀次的完整备份。因为所有类型的备份都基于完整备份,如果没有最少⼀次完整备份,其他类型的备份都是多余的,所以在这⾥强调⼀下,在创建完⼀个新数据库之后,强烈建议甚⾄强制做⼀次完整备份。
SELECT database_name,recovery_model,name
FROM msdb.dbo.backupset
使⽤上⾯的语句粗略可以看到有那些数据库做过备份,由于测试,所以做了⼏次备份,可以看到我这个时间点已经做了备份了。
(3)、确保别⼈不再连接数据库,然后做⼀次⽇志尾部备份:
⾸先先创建⼀点数据:
/*
由于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命令,让它在某个时间发⽣,这样恢复的时候就有准确性:
USE AdventureWorks
GO
WAITFOR TIME '21:45'
DELETE stRestore
现在来看看数据:
USE AdventureWorks
GO
SELECT * stRestoretruncatedelete
到这⼀步,灾难出现了。但是切记要冷静。
下⾯就是本⽂的重点开始,做⼀次⽇志备份,最重要是选择【备份⽇志尾部】
然后在【选项】页选择:除【事务⽇志】除,其他红框包裹的地⽅为强烈建议勾选的地⽅。并且保证数据库不要有别⼈在连接,因为备份⽇志尾部会使数据库处于还原状态,拒绝其他会话的连接,如果不断开其他连接,是备份不了的。
然后按确定,当然,可以使⽤上⽅的【脚本】来⽣成语句:
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杀掉:
SELECT * FROM sys.sysprocesses WHERE dbid=DB_ID('AdventureWorks')
执⾏结果:
然后kill掉。
接着继续备份。
然后进⾏还原,如图:
先要还原完整备份,选择最近的那次,由于⽇志备份的特性(以后其他⽂章再说),只认最后⼀次备份,所以要选择最新的那次,否则还原不了。
这⾥⼜有⼀个注意事项,记得选择:
接着还原⽇志⽂件,这是最最重要的⼀步:
然后:
由于实验的时候出了点问题,后⾯重做了,所以时间选择到22:19分,我是在22:20分删除数据的。这⾥不⽤太在意,只要把时间点指定到你误删除的时间之前即可。⽽由于⽇志尾部备份都是最后⼀个备份⽂件,所以这⾥选则红框部分即可:
现在再检查⼀下:
可以看到,数据已经还原成功。
总结:
平时不做备份,出问题来喊急,这是苟有⾃取,还有⼀些脑袋发热的⼈喜欢看到ldf很⼤就直接删除,那以后出问题就别怪微软了。
本⽂中的⽅法看上去有点繁琐,但是实操⼏次就觉得好了,但是步骤建议严格按照上⾯说的,因为⼀旦操作错误,就很⿇烦,此时再次强调——冷静冷静再冷静
这种⽅法有⼏个缺点:
1、如果你发现误操作以后还有很多⼈做了操作,那么你还原成功后,别⼈的操作就会冲掉,所以发⽣误操作后,要马上停⽌别⼈对数据库的操作。
2、这个⽅法要对数据库独占,所以你想偷偷恢复是不⾏的了。勇敢承认错误吧。
--------------------------------------------------------------------------------------------------------------------------

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。