前言:
今天花了四个小时的时间总结了下文件备份和还原的相关资料,还算是有些收获吧,该文我参考了某些前辈的文章,下面是相关的链接,我增加了更多的细节和自己的想法:
一、文件组的创建、备份以及还原
-- 测试环境USE masterGO-- DROP DATABASE [Demo]CREATE DATABASE [Demo]ON PRIMARY ( NAME = N'Demo', FILENAME = N'D:\MSSQLDATA\Demo.mdf' , SIZE = 5120KB , FILEGROWTH = 1024KB ), FILEGROUP [FG1] ( NAME = N'Demo01', FILENAME = N'D:\MSSQLDATA\Demo01.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB ), FILEGROUP [FG2] ( NAME = N'Demo02', FILENAME = N'D:\MSSQLDATA\Demo02.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB ), FILEGROUP [FG3] ( NAME = N'Demo03', FILENAME = N'D:\MSSQLDATA\Demo03.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB )LOG ON ( NAME = N'Demo_log', FILENAME = N'D:\MSSQLDATA\Demo_log.ldf' , SIZE = 5120KB , FILEGROWTH = 10MB)GOALTER DATABASE [Demo] SET RECOVERY FULL WITH NO_WAITGO USE [Demo]GO-- drop table dbo.TABCREATE TABLE dbo.TAB( Guid uniqueidentifier not null, name nvarchar(50) not null, sex bit not null, age smallint not null, indate datetime not null, --CONSTRAINT [PK_TAB] PRIMARY KEY CLUSTERED ([Guid] ASC)ON [FG3]) ON [FG3]GOALTER TABLE dbo.TAB ADD CONSTRAINT [DF_TAB_Guid] DEFAULT(NEWSEQUENTIALID()) FOR [Guid]GOALTER TABLE dbo.TAB ADD CONSTRAINT [DF_TAB_sex] DEFAULT(1) FOR [sex]GOALTER TABLE dbo.TAB ADD CONSTRAINT [DF_TAB_indate] DEFAULT(GETDATE()) FOR [indate]GO USE [Demo]GO-- drop table dbo.TAB2CREATE TABLE dbo.TAB2( Guid uniqueidentifier not null, name nvarchar(50) not null, sex bit not null, age smallint not null, indate datetime not null,) ON [PRIMARY]GOALTER TABLE dbo.TAB2 ADD CONSTRAINT [DF_TAB2_Guid] DEFAULT(NEWSEQUENTIALID()) FOR [Guid]GOALTER TABLE dbo.TAB2 ADD CONSTRAINT [DF_TAB2_sex] DEFAULT(1) FOR [sex]GOALTER TABLE dbo.TAB2 ADD CONSTRAINT [DF_TAB2_indate] DEFAULT(GETDATE()) FOR [indate]GO INSERT INTO Demo.dbo.TAB(name ,age) SELECT 'KK',10GO 5INSERT INTO Demo.dbo.TAB2(name ,age) SELECT 'KK',10GO 5 -- TAB 在文件组 FG3(Demo03) ; TAB2 在文件组 PRIMARY . use masterGO --------------------------------------------------------/*************** 数据库文件备份还原测试 ***************/-------------------------------------------------------- -- (某个时间)备份文件Demo03BACKUP DATABASE Demo FILE = 'Demo03' TO DISK = 'D:\MSSQLDATA\backup\Demo_file_Demo03.bck' WITH INIT , COMPRESSIONGO -- 更改数据UPDATE Demo.dbo.TAB SET name='OO'GOUPDATE Demo.dbo.TAB2 SET name='OO'GO -- 备份当前日志, you must add NO_TRUNCATE in statement end,it's tail of log, otherwise, you still can't query TAB after restore logBACKUP LOG Demo TO DISK = 'D:\MSSQLDATA\backup\Demo_log.bck' WITH INIT , NO_TRUNCATEGO -- 还原文件 Demo03RESTORE DATABASE [Demo] FILE = N'Demo03' FROM DISK = N'D:\MSSQLDATA\backup\Demo_file_Demo03.bck' WITH NORECOVERYGO /*此时文件组 FG3(Demo03)不能访问,但其他文件组的表可以正常访问!*/ -- 重做后来的日志RESTORE LOG [Demo] FROM DISK = N'D:\MSSQLDATA\backup\Demo_log.bck' WITH RECOVERYGO ------ 完成!SELECT * FROM Demo.dbo.TABSELECT * FROM Demo.dbo.TAB2
备注: no_truncate: 相当于COPY_ONLY和CONTINUE_AFTER_ERROR。使用NO_TRUNCATE备份日志,不会截断日志(仅相当于拷贝日志),所以如果后面有日志备份的话可以跨过这个尾日志,因为它不会截断,也可以在数据库发生错误时使用NO_TRUNCATE备份尾日志。
二、当主文件异常但是日志文件是好的并且SQLSERVER实例运行正常的时候,操作如下:
create table _m(c1 int)select * from _minsert _mselect 0BACKUP DATABASE test TO DISK = 'D:\MSSQLDATA\backup\test.bck' WITH INIT BACKUP LOG test TO DISK = 'D:\MSSQLDATA\backup\test_log.bck' WITH INIT --, NO_TRUNCATEinsert _m select 1--关掉SQL SERVER SERVICES,拿掉test DB的MDF文件,让文件处于不可用状态--开启SQLSERVERBACKUP LOG test TO DISK = 'D:\MSSQLDATA\backup\test_log1.bck' WITH INIT , NO_TRUNCATE--开启SQLSERVER这一步不需要删除挂起的DB也可以做的RESTORE DATABASE test FROM DISK = N'D:\MSSQLDATA\backup\test.bck' WITH NORECOVERYRESTORE LOG test FROM DISK = N'D:\MSSQLDATA\backup\test_log.bck' WITH NORECOVERYRESTORE LOG test FROM DISK = N'D:\MSSQLDATA\backup\test_log1.bck' WITH RECOVERY--成功了select * from TEST.DBO._m
三、与二不同的是,连SQLSERVER实例都不能运行的时候,你需要将完整备份和后面需要的所有的日志备份以及ldf文件copy到其他实例上面,我们需要获取最后的一个尾日志。
1、在新的实例上面新建一个名称一样的DB,并且设置成脱机的状态,删除新建数据库的MDF文件,将需要备份的数据库的日志文件替换掉原有的LDF文件。
2、设置DB为联机状态,由于没有mdf文件,DB是不可用的
3、进行尾日志备份(注:如果系统提示权限的不够的相关报错,那你就需要把存放数据库文件的文件夹设置成“完全控制”的权限)
4、依次还原 完整备份--所有的日志备份---最后的尾日志备份
以上都是只有一个数据文件的,如果有多个数据文件的话后面有时间更新吧,已经晚上11点多了,休息了。