sql-server – 恢复数据库,不包括FILESTREAM数据

前端之家收集整理的这篇文章主要介绍了sql-server – 恢复数据库,不包括FILESTREAM数据前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
上下文
我们正在开发一个底部有大型数据库的系统.它是在sql Server 2008 R2上运行的MS sql数据库.数据库的总大小约为12 GB.

其中,大约8.5 GB位于单个表BinaryContent中.顾名思义,这是一个表格,我们将任何类型的简单文件直接存储在表格中作为BLOB.最近我们一直在测试使用FILESTREAM将所有这些文件数据库移出到文件系统的可能性.

我们对数据库进行了必要的修改,没有任何问题,我们的系统在迁移后仍能正常工作. BinaryContent表看起来大致如下:

CREATE TABLE [dbo].[BinaryContent](
    [BinaryContentID] [int] IDENTITY(1,1) NOT NULL,[FileName] [varchar](50) NOT NULL,[BinaryContentRowGUID] [uniqueidentifier] ROWGUIDCOL  NOT NULL
) ON [PRIMARY] FILESTREAM_ON [FileStreamContentFG]
ALTER TABLE [dbo].[BinaryContent] ADD [FileContentBinary] [varbinary](max) FILESTREAM  NULL
ALTER TABLE [dbo].[BinaryContent] ADD  CONSTRAINT [DFBinaryContentRowGUID]  DEFAULT (newsequentialid()) FOR [BinaryContentRowGUID]

所有内容都驻留在PRIMARY文件组中,但FileBinaryContent字段除外,它位于单独的文件组FileStreamContentFG中.

脚本
从开发人员的角度来看,我们经常喜欢从生产环境中获取数据库的新副本,以便能够处理最新数据.在这些情况下,我们很少对BinaryContent中存储的文件感兴趣(现在使用FILESTREAM).

我们几乎按照我们的意愿行事.我们备份数据库,没有像这样的文件流:

BACKUP DATABASE FileStreamDB
FILEGROUP = 'PRIMARY' 
TO DISK = 'c:\backup\FileStreamDB_WithoutFS.bak' WITH INIT

并像这样恢复它:

RESTORE DATABASE FileStreamDB
FROM DISK = 'c:\backup\FileStreamDB_WithoutFS.bak'

这似乎工作正常,只要我们避免使用FileBinaryContent字段的部分,我们的系统就可以工作.例如,我们可以运行以下查询而不会出现问题:

SELECT TOP 10 [BinaryContentID],[FileName],[BinaryContentRowGUID]
--,[FileContentBinary]
FROM [dbo].[BinaryContent]

当然,如果我取消注释上面的行,包括查询中的FileContentBinary,我会收到一个错误

Large object (LOB) data for table “dbo.BinaryContent” resides on an
offline filegroup (“FileStreamContentFG”) that cannot be accessed.

我们的系统处理内容设置为null的文件,所以我想做的是这样的:

UPDATE [dbo].[BinaryContent]
SET [FileContentBinary] = null

但这当然给了我同样的错误.此时我被困住了.


有没有办法恢复数据库而不必从FileStreamContentFG文件组恢复所有内容?可以通过在我上面尝试时将值更新为null,或者在文件丢失时默认为null或者什么?

或者我是否可能以错误的方式解决问题?

我本质上是一名开发人员,并且作为一名DBA没有太多的知识,所以如果我在这里忽略了一些微不足道的事情,请原谅.

解决方法

您尝试做的事情会使数据库处于(事务上)不一致的状态,因此无法实现.

Partial Database Availability whitepaper是一个有用的参考指南,包括如何检查特定表或文件是否在线的示例.如果您的数据访问是通过存储过程进行的,则可以相对轻松地合并该检查.

在您的场景中可能值得一看的一种替代(但有些hacky)方法是隐藏表并用视图替换它.

-- NB: sqlCMD script
:ON ERROR EXIT
:setvar DatabaseName "TestRename"
:setvar FilePath "D:\MSsql\I3\Data\"

SET STATISTICS TIME OFF;
SET STATISTICS IO OFF;
SET NOCOUNT ON;
GO

USE master;
GO

IF EXISTS (SELECT name FROM sys.databases WHERE name = N'$(DatabaseName)')
  DROP DATABASE $(DatabaseName)
GO

CREATE DATABASE $(DatabaseName) 
ON PRIMARY 
  (
  NAME = N' $(DatabaseName)',FILENAME = N'$(FilePath)$(DatabaseName).mdf',SIZE = 5MB,MAXSIZE = UNLIMITED,FILEGROWTH = 1MB
  ),FILEGROUP [FG1] DEFAULT
  ( 
  NAME = N' $(DatabaseName)_FG1_File1',FILENAME = N'$(FilePath)$(DatabaseName)_FG1_File1.ndf',SIZE = 1MB,FILEGROWTH = 1MB 
  ),FILEGROUP [FG2] CONTAINS FILESTREAM
  ( 
  NAME = N'$(DatabaseName)_FG2',FILENAME = N'$(FilePath)Filestream'
  )
LOG ON 
  ( 
  NAME = N'$(DatabaseName)_log',FILENAME = N'$(FilePath)$(DatabaseName)_log.ldf',FILEGROWTH = 1MB
  )
GO

USE $(DatabaseName);
GO

CREATE TABLE [dbo].[BinaryContent](
    [BinaryContentID] [int] IDENTITY(1,[BinaryContentRowGUID] [uniqueidentifier] ROWGUIDCOL UNIQUE DEFAULT (NEWSEQUENTIALID()) NOT NULL,[FileContentBinary] VARBINARY(max) FILESTREAM  NULL
) ON [PRIMARY] FILESTREAM_ON [FG2]
GO 

-- Insert test rows
INSERT
  dbo.BinaryContent
  (
  [FileName],[FileContentBinary]
  )
VALUES
  (
  CAST(NEWID() AS VARCHAR(36)),CAST(REPLICATE(NEWID(),100) AS VARBINARY)
  );
GO 100

USE master;
GO

-- Take FILESTREAM filegroup offline
ALTER DATABASE $(DatabaseName)
MODIFY FILE (NAME = '$(DatabaseName)_FG2',OFFLINE)
GO

USE $(DatabaseName);
GO

-- Rename table to make way for view
EXEC sp_rename 'dbo.BinaryContent','BinaryContentTable','OBJECT';
GO

-- Create view to return content from table but with NULL FileContentBinary
CREATE VIEW dbo.BinaryContent
AS

SELECT
  [BinaryContentID],[BinaryContentRowGUID],[FileContentBinary] = NULL
FROM
  [dbo].[BinaryContentTable];
GO

-- Check results as expected
SELECT TOP 10
  *
FROM
  dbo.BinaryContent;
GO

猜你在找的MsSQL相关文章