前几天同事不小心误操作,将SQLServer库的一张表的一个状态字段给刷成了一个统一状态,由于是update执行所以原来的相关状态无法确定。发生这种事情的时候我的小伙伴背后 一凉。
由于是在开发试运行中的项目,还没来得及进行备份处理,所以从备份恢复宣告失败。就算有备份那么恢复的也是备份时间节点的数据,意味着使用平台做的数据需要从备份时间重新做过,而且有可能有遗漏。
小伙伴问我这咋办,首先没有备份,那么只有从数据库日志查找,然后看能不能通过日志找回之前的数据,再还原到刷状态之前的数据。然后就找到了ApexSQLLog工具,接下来我介绍下这款工具的使用和如何恢复数据。ApexSQLLog有几个版本,我是用的是ApexSQLLog2014支持SqlServer更高的版本,数据库使用的是SqlSerVer2014。
ApexSQLLog2014
提取码: np4f
-
首先建一个测试库,和一张测试表。
测试库ApexSQLLogTest和测试用的表TestUser,然后我手动编辑了三条数据进去,保存编辑的数据。
-
用ApexSQLLog打开测试库日志
选择要连接的数据库,也可以从最近的session中打开,打开筛选过的记录可以保存未session。
然后选中要筛选的日志文件,如果有备份数据库文件也会自动查找到并在这里罗列出来,自己按情况选择。
-
条件筛选
我们选择日志文件后就进入到筛选条件选择,可以在筛选条件里面自由组合。
可以选择时间段(Time range)、操作(operations)、表(tables)。
高级选项(advanced options)里面还有用户、字段条件等可以选择。
-
查看日志数据
当我们组合完筛选条件后,就进入到日志分析界面,可以看到我们之前手动插入的三条数据实际已经在日志里面了,分成了三条insert语句。在选中其中一条日志的时候在下面可以看到执行的各字段值的修改情况。
可以点击 下面的Row history查看记录,Redo script可以生成执行的操作, Undo script可以还原到之前的数据。我们恢复数据就是使用Undo script。
-
恢复数据测试。
我们使用update语句将Status状态全都重置为3。
update TestUser set Status=3
然后刷新下日志,会看到多出了三条Update日志记录,点击第一条看到下面的Status字段从0变为了3。
我们选中这三条记录右键或者上面的菜单栏功能,用create undo script 生成恢复sql。
-- This UNDO script was generated with ApexSQL Log 2014.04.1133 on 2020-06-10 11:18:47.601
-- NOTE: Operations in UNDO scripts are always output in descending order.
-- SERVER VIP-966SQLEXPRESS
-- DATABASE ApexSQLLogTest
-- UPDATE (00000024:000000A0:0004) done at 2020-06-10 11:09:36.293 by VIP-966Administrator in transaction 0000:0000034B (Committed)
BEGIN TRANSACTION
UPDATE [dbo].[TestUser] SET [Status] = 2 WHERE [Id] = 3
IF @@ROWCOUNT <= 1 COMMIT TRANSACTION ELSE BEGIN ROLLBACK TRANSACTION; PRINT 'ERROR: STATEMENT AFFECTED MORE THAN ONE ROW. ALL THE CHANGES WERE ROLLED BACK.' END
-- UPDATE (00000024:000000A0:0003) done at 2020-06-10 11:09:36.293 by VIP-966Administrator in transaction 0000:0000034B (Committed)
BEGIN TRANSACTION
UPDATE [dbo].[TestUser] SET [Status] = 1 WHERE [Id] = 2
IF @@ROWCOUNT <= 1 COMMIT TRANSACTION ELSE BEGIN ROLLBACK TRANSACTION; PRINT 'ERROR: STATEMENT AFFECTED MORE THAN ONE ROW. ALL THE CHANGES WERE ROLLED BACK.' END
-- UPDATE (00000024:000000A0:0002) done at 2020-06-10 11:09:36.293 by VIP-966Administrator in transaction 0000:0000034B (Committed)
BEGIN TRANSACTION
UPDATE [dbo].[TestUser] SET [Status] = 0 WHERE [Id] = 1
IF @@ROWCOUNT <= 1 COMMIT TRANSACTION ELSE BEGIN ROLLBACK TRANSACTION; PRINT 'ERROR: STATEMENT AFFECTED MORE THAN ONE ROW. ALL THE CHANGES WERE ROLLED BACK.' END
GO
-- FINISHED ON 2020-06-10 11:18:47.697
-- TOTAL OPERATIONS PROCESSED 3
-- END OF FILE
最后我们就可以使用这个脚本去恢复数据了。
注意
我们在使用日志恢复的时候如果表有主键会根据主键生成sql,如上图sql中 where后面的条件。如果表没有主键那么生成的sql后面的where条件会带上所有的字段。在我帮小伙伴恢复数据的时候发现他的表没有设置主键,而且字段有20多个,3万多条数据生成的sql都是100多M,还要拆分执行。
比如我把Id主键去了再更新下Status状态到4,生成的sql如下,会提示没有主键。
以上就是一次数据恢复的分享,如果下次你也遇到这种情况希望能帮到你。