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