加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

SQLServer 2008以上误操作数据库恢复方法——日志尾部备份

发布时间:2020-12-12 13:03:02 所属栏目:MsSql教程 来源:网络整理
导读:原文出处:http://www.voidcn.com/article/p-kkmcngjp-ov.html 问题: ? ? ? ? ?经常看到有人误删数据,或者误操作,特别是update和delete的时候没有加where,然后就喊爹喊娘了。人非圣贤孰能无过,做错可以理解,但不能纵容,这个以后再说,现在先来解决问
原文出处:http://www.voidcn.com/article/p-kkmcngjp-ov.html

问题:

? ? ? ? ?经常看到有人误删数据,或者误操作,特别是update和delete的时候没有加where,然后就喊爹喊娘了。人非圣贤孰能无过,做错可以理解,但不能纵容,这个以后再说,现在先来解决问题。

? ? ? ? 遇到这种情况,一般都是没有做备份,不然也不会来发问了。首先要冷静,否则会有更大的灾难。直到你放弃。


解决方法:

? ? ? ?对于这类问题,主要是找回误操作之前的数据,在2008之前,有个很出名的工具Log Exploer,听说还挺好用的,这个网上大把教程,这里就不多说了。但是唯一遗憾的是,不支持2008及更高版本,这时除了其他第三方工具,那么最常用的就是本文提到的方法——日志尾部备份。本文实验环境2008R2,对于2008及其以上版本可以使用这个方法,其实2005也可以,2000很少用,没试过,只是2008之前可以使用Log Exploer,所以就没必要用这种方法。

? ? ? 下面图文并茂讲解操作方法,至于原理,不属于本文范围,而且我相信真遇到误操作的时候,估计没人会看原理了。

步骤:

(1)、检查数据库的恢复模式,如图:



或者使用脚本检查:

[sql]? view plain copy print ?

在CODE上查看代码片

派生到我的代码片

  1. SELECT?recovery_model,recovery_model_desc??
  2. FROM?sys.databases??
  3. WHERE?name?='AdventureWorks'??

结果如下:


? ? ? ? 确保数据库的恢复模式最起码不能为【简单】。至于如何修改成完整模式,我觉得这些应该没必要多说了。

?

? ? ? ?切记,对于任何重要环境,不仅仅是客户正式环境(俗称生产环境),都强烈建议使用【完整恢复模式】,虽然对于另外两种(大容量日志(BULK_LOGGED)、简单(SIMPLE))来说,完整恢复模式产生的日志会大,但是在出现问题的时候,就会觉得这些都不算什么了。并且我也想不到任何理由对于正式环境不使用完整恢复模式。只要管理得当,完整恢复模式的日志也不会太变态。

(2)、这里其实隐含另外一步,曾经做过最少一次的完整备份。因为所有类型的备份都基于完整备份,如果没有最少一次完整备份,其他类型的备份都是多余的,所以在这里强调一下,在创建完一个新数据库之后,强烈建议甚至强制做一次完整备份。

派生到我的代码片

    SELECT??database_name,recovery_model,name???
  1. FROM?msdb.dbo.backupset??

使用上面的语句粗略可以看到有那些数据库做过备份,由于测试,所以做了几次备份,可以看到我这个时间点已经做了备份了。


(3)、确保别人不再连接数据库,然后做一次日志尾部备份:

首先先创建一点数据:

派生到我的代码片

    /*??
  1. 由于tempdb永远为简单恢复模式,所以不适合做案例。??
  2. 这里使用微软的示例数据库AdventureWorks??
  3. */??
  4. USE?AdventureWorks??
  5. GO??
  6. IF?OBJECT_ID('testRestore')?IS?NOT?NULL???
  7. ????DROP?TABLE?testRestore??
  8. GO??
  9. CREATE? ????(??
  10. ??????id?INT?IDENTITY(1,?1)?,??
  11. ??????NAME?VARCHAR(50)??
  12. ????);??
  13. --插入测试数据:?????
  14. INSERT?INTO?testRestore(Name)??
  15. SELECT?'test1'??
  16. UNION?ALL???
  17. SELECT?'test2'??
  18. SELECT?'test3'??
  19. SELECT?'test4'??
  20. SELECT?'test5'??
  21. SELECT?'test6'??
  22. SELECT?'test7'??
  23. SELECT?'test8'??
  24. SELECT?*?FROM?testRestore??
检查一下结果:



然后来做个删除操作,为了定位是啥时候发生的,我加了一个waitfor命令,让它在某个时间发生,这样恢复的时候就有准确性:

派生到我的代码片

    USE?AdventureWorks??
  1. WAITFOR?TIME?'21:45'??
  2. DELETE?FROM?dbo.testRestore??

现在来看看数据:

派生到我的代码片


    到这一步,灾难出现了。但是切记要冷静

    下面就是本文的重点开始,做一次日志备份,最重要是选择【备份日志尾部】



    然后在【选项】页选择:除【事务日志】除,其他红框包裹的地方为强烈建议勾选的地方。并且保证数据库不要有别人在连接,因为备份日志尾部会使数据库处于还原状态,拒绝其他会话的连接,如果不断开其他连接,是备份不了的。




    然后按确定,当然,可以使用上方的【脚本】来生成语句:


    派生到我的代码片

      USE?Master??
    1. 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??
    2. declare?@backupSetId?as?int??
    3. select?@backupSetId?=?position?from?msdb..backupset?where?database_name=N'AdventureWorks'?and?backup_set_id=(select?max(backup_set_id)?where?database_name=N'AdventureWorks'?)??
    4. if?@backupSetId?is?null?begin?raiserror(N'验证失败。找不到数据库“AdventureWorks”的备份信息。',?16,?1)?end??
    5. RESTORE?VERIFYONLY?FROM??DISK?=?N'E:AdventureWorks.bak'?WITH??FILE?=?@backupSetId,??NOUNLOAD,??NOREWIND??
    6. GO??

    此时,数据库会处于【正在还原】的状态


    如果发现备份不了可以用下面语句查看,并把spid杀掉:


    派生到我的代码片

      SELECT??*?FROM?sys.sysprocesses?WHERE?dbid=DB_ID('AdventureWorks')??

    执行结果:


    然后kill掉。

    接着继续备份。

    然后进行还原,如图:

    先要还原完整备份,选择最近的那次,由于日志备份的特性(以后其他文章再说),只认最后一次备份,所以要选择最新的那次,否则还原不了。



    这里又有一个注意事项,记得选择:



    接着还原日志文件,这是最最重要的一步:



    然后:



    由于实验的时候出了点问题,后面重做了,所以时间选择到22:19分,我是在22:20分删除数据的。这里不用太在意,只要把时间点指定到你误删除的时间之前即可。而由于日志尾部备份都是最后一个备份文件,所以这里选则红框部分即可:


    现在再检查一下:



    可以看到,数据已经还原成功。

    ?

    总结:

    平时不做备份,出问题来喊急,这是苟有自取,还有一些脑袋发热的人喜欢看到ldf很大就直接删除,那以后出问题就别怪微软了。

    本文中的方法看上去有点繁琐,但是实操几次就觉得好了,但是步骤建议严格按照上面说的,因为一旦操作错误,就很麻烦,此时再次强调——冷静冷静再冷静!!!!!!

    这种方法有几个缺点:

    1、?????????????如果你发现误操作以后还有很多人做了操作,那么你还原成功后,别人的操作就会冲掉,所以发生误操作后,要马上停止别人对数据库的操作。

    2、?????????????这个方法要对数据库独占,所以你想偷偷恢复是不行的了。勇敢承认错误吧。

    对于核心数据表,还是要先做好预防操作,可以看:SQLServer恢复表级数据。

    关于备份,可以看我的另外一篇文章:第一篇——第一文 SQL Server 备份基础

    (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读