你的位置:首页 > 数据库

[数据库]SQL Server 数据库备份还原和数据恢复



随笔 - 62  文章 - 12  评论 - 283 

博客园  首页  新随笔  联系  管理  订阅  

认识数据库备份和事务日志备份

数据库备份与日志备份是数据库维护的日常工作,备份的目的是在于当数据库出现故障或者遭到破坏时可以根据备份的数据库及事务日志文件还原到最近的时间点将损失降到最低点。

 

数据库备份

数据库备份可以手动备份和语句备份

一.手动备份数据库

1.鼠标右键选择你要进行备份的数据库-任务-备份

可以在常规选项页面你可以选择备份类型是进行完整数据库备份还是差异数据库备份

2.点击添加选项,选择数据库文件的存放路径

注意文件名记得加后缀.bak,便于恢复时的查找

3.你还可以在选项页面是追加到现有的备份集,还是覆盖所有的现有备份集,还可以选择备份验证完整性(建议选择),还可以选择是否压缩备份等。

二.语句备份数据库

use master goBACKUP DATABASE [test] TO DISK = N'D:\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Backup\test.bak' WITH NOFORMAT, NOINIT, NAME = N'test-完整 数据库 备份', SKIP, NOREWIND, NOUNLOAD, STATS = 10GO

数据库日志备份

      首先需要注意,数据库日志的备份是基于数据库完整备份,也就是说你备份数据库日志之前你首先要先对数据库进行一次完整的备份,因为之间会涉及到坚持到检查点lsn,这也是本文接下来要讲的重点。

一.手动备份数据库日志

1.右键数据库-任务-备份-选择备份类型(事务日志)

2.点添加,添加日志文件备份存储路径

3.同数据库完整备份一样,你也可以选择覆盖现有备份集或者追加到现有备份集,这里现在覆盖现有备份集、验证完整性,然后确认备份

二.语句备份数据库事务日志

BACKUP LOG [test] TO DISK = N'D:\test.trn' WITH NOFORMAT, INIT, NAME = N'test-事务日志 备份', SKIP, NOREWIND, NOUNLOAD, STATS = 10GO

数据库还原

右键数据库-还原数据库-添加需要进行还原的数据库文件路径

在还原源选项中你可以选择‘源数据库’,‘源设备’。1.选择源数据库工具会自动显示该数据库之前的一些备份,然后直接选择需要还原的数据库备份集。

2.选择源设备点击后面的...,添加需要还原的数据库文件

2.点击确认还原数据库

数据库恢复

数据库恢复的前提是1.一个完整的数据库备份2.包含这个完整数据库备份的事务日志备份3.完整备份之间也可以存在数个差异备份

对于数据库维护空间始终是一个比较头疼的问题,特别是对于大型数据库而言,每天的日志文件增长是庞大的,很多数据库管理员会定时对数据库日志文件进行收缩,但是经常收缩会存在收缩完日志文件还是不能减少,这是因为存在很多活动的日志无法收缩可以用

复制代码
DBCC LOGINFO('数据库名称')  我们看到status=0的日志,代表已经备份到磁盘的日志文件;而status=2的日志还没有备份。当我们收缩日志文件时,收缩掉的空间其实就是status=0的空间,如果日志物理文件无法减小,这里一定能看到非常多status=2的记录
复制代码

 

 解决办法:1.可以分离要收缩的数据库,然后手动删除日志文件,然后附加数据库,数据库就会产生一个很小的日志文件(不推荐使用这种方法)

2.右键要出来的数据库选择“属性”-"选项",将恢复模式改成"简单",然后利用收缩工具可以讲日志文件收缩到很小,收缩完记得讲恢复模式改成"完整"

也可以用语句进行处理(dbname是你要进行收缩的数据库名,dbname_log是你要进行收缩的数据库的逻辑日志名称)

复制代码
USE [master]  GO  ALTER DATABASE [dbname] SET RECOVERY SIMPLE WITH NO_WAIT  GO  ALTER DATABASE [dbname] SET RECOVERY SIMPLE  --简单模式  GO  USE [dbname]  GO  DBCC SHRINKFILE (N'dbname_log' , 11, TRUNCATEONLY)  GO  USE [master]  GO  ALTER DATABASE [dbname] SET RECOVERY FULL WITH NO_WAIT  ALTER DATABASE [dbname] SET RECOVERY FULL
复制代码

对于第一种方法不赞同使用,首先对于数据库的分离与附加有时候会破坏数据库,造成数据库无法还原,还有就是对于在线数据库也不允许进行分离操作。

对于第二种方法是slq2008收缩日志文件的一种方法,但是此方法也不能使用过于频繁,因为进行数据库恢复模式的更改会截断事务日志文件,这样的话当时利用事务日志文件进行恢复的时候检查点不能包含数据库文件,而且当你要对事务日志进行备份的时候会重新提示你需要对数据库进行完整备份。

举个例子:比如你昨天晚上进行了一次完整备份,然后同时你也进行了一次日志备份,然后你每个小时进行过一次差异备份,最近的差异备份时间点是14点,如果此时数据库错误修改了数据,你可以立马备份一个日志文件将数据库恢复到日志备份开始到日志备份终点前的任意时间点 。

如果此时你进行了修改数据库模式,截断日志进行了收缩,那么你的数据只能恢复到昨天晚上备份的那个日志备份时间前的任意时间点,也就是今天所做的数据库更改无法再恢复了,因为日志文件已经被截断了.

因为日志文件的检查点(lsn)是连续的,每一次日志备份都是在上一次备份的基础上lsn往后增加的,lsn的范围也包括了数据库文件的lsn,也只有日志文件的lsn包括了数据库文件的lsn,才能将数据库文件进行回滚。

 

总结

备份还原看似简单,而且现在的图形化的工具更加让人对备份还原的理解不够深入,特别的日志备份如果你不仔细研究一下会存在很多误区。

1.完整备份和差异备份的BAK中也会备份日志文件,在备份的时候生成检查点但是该检查点只是标识(好比将日志文件进行归档,当我们查询fn_dblog的时候发现日志少了,但实际上日志文件还是存在的,当你这时候备份日志的时候你依然会备份到那部分归档掉的日志,但是备份日志的时候生成检查点checkpoin就会将日志进行截断,将不活动的那部分日志清空)作用并不截断日志。

2.当日志进行第一次备份的时候是自最近一次完整备份之后的日志进行备份,当下次再进行日志备份(前提日志未被截断)的时候是备份上一次日志备份的last_lsn之后到当前备份之间的日志记录,不管中间是否存在完整或者差异备份都不会减少日志的量,不要误理解为当上一次备份日志之后中间存在完整备份然后再备份日志备份的日志记录就是完整备份之后的记录。

3.第一次的日志备份的first_lsn一定是和日志备份之前的完整备份的first_lsn相同,如果备份集最后一次备份是日志备份那么最后一次日志备份的last_lsn一定包含自第一次完整备份以来所有的完整好差异备份的last_lsn。所有可以通过第一次完整备份和第一个日志备份和最后一个日志备份(中间没有日志备份)还原数据库到第一次完整备份之后的任何一个时间点,无论中间是否存在完整差异备份。

4.为什么备份集之间需要完整或者差异备份,如果没有完整或者差异备份如果自第一次备份以来很长时间没有进行完整或者差异备份那么当进行故障还原的时候需要耗费很长的时间,当中间如果存在差异备份的时候那么还原日志的时间将大大减少,不需要在执行完整到差异这部分的redo/undo。

5.由于SQLSERVER是日志先写的机制,所以当数据库出现故障也是数据出现了故障一般都是进行了写日志操作但是在写数据的时候出现了什么问题,所以当进行日志的还原操作的时候会进行这些检查,保证事务的一致性这也是为什么DBCC CHECKDB检查数据库错误一般还原是最好的方法,当你将日志进行还原的时候所有的日志备份的操作都会重新进行操作一次。

6.差异备份的原理,差异备份与日志备份不一样,日志备份是每次的备份都是自上一次备份以来的增量,差异备份是自上一次完整备份以来的增量,所以无论中间有多少次差异备份,都只需要还原完整备份与最后一次差异备份即可。