FILESTREAMデータを除くデータベースの復元


20

コンテキスト
下部に大規模なデータベースを持つシステムを開発しています。これは、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クエリを含む上記の行のコメントを外すと、エラーが発生します。

テーブル "dbo.BinaryContent"のラージオブジェクト(LOB)データは、アクセスできないオフラインファイルグループ( "FileStreamContentFG")にあります。

私たちのシステムハンドルコンテンツがに設定されているファイルをnull、私はどうなるかので、好き行うには、次のようなものです:

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

しかし、これはもちろん上記と同じエラーを私に与えます。この時点で立ち往生しています。

質問ファイルグループ
からすべてを復元せずにデータベースを復元する方法はありFileStreamContentFGますか?上記のように値をnullに更新するか、ファイルが見つからないか何かがデフォルトのときにnullになりますか?

または、私はおそらく間違った方法で問題に近づいていますか?

私は本質的に開発者であり、DBAとしての知識はあまりないので、ここで些細なことを見落としているのであれば、すみません。


[BinaryContent] FILEGROUPからいくつかのデータを取得し、それを更新するときにプライマリファイルグループの復元を行うために、完全復元を1回実行できますか?
jgardner04

@ jgardner04:うまくいかないようです。最初に完全復元を実行し、その後プライマリファイルグループのみを含むバックアップを復元すると、データベースは一貫性のない状態になります(エラーメッセージ:「ログが復元されなかったため、データベースを復元できません(...) 1つ以上のRESTOREステップが必要なため、データベースをオンラインにできませんでした」)。
ジュリアン

dbo.BinaryContentへのアクセスは常にストアドプロシージャ経由ですか?何人が関与していますか?
マークストーリースミス

@ MarkStorey-Smith:データベースは、主に通常のクエリを使用して、NHibernateを介してアクセスされます(ASP.NET WebアプリケーションとWindowsフォームアプリケーションの両方から)。それはどのように関連していますか?
ジュリアン

2
アクセスがストアドプロシージャを介している場合、部分的な可用性/断片的な復元からのアプローチを適用して、どのファイルグループがオンラインであるかを確認できます。正直に言うと、12GBでは、完全に復元するだけで、実際に回避する価値はありません。
マークストーリースミス

回答:


10

あなたがやろうとしていることは、データベースを(トランザクション的に)一貫性のない状態のままにするため、それは不可能です。

データベース部分的な可用性に関するホワイトペーパーは、有用なリファレンスガイドであり、特定のテーブルまたはファイルがオンラインであるかどうかを確認する方法の例を含んでいます。データアクセスがストアドプロシージャを介している場合、そのチェックを比較的簡単に組み込むことができます。

シナリオで一見の価値があるかもしれない別の(しかし多少ハッキングな)アプローチは、テーブルを非表示にしてビューに置き換えることです。

-- 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
  , MAXSIZE = UNLIMITED
  , 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'
  , SIZE = 1MB
  , MAXSIZE = UNLIMITED
  , FILEGROWTH = 1MB
  )
GO

USE $(DatabaseName);
GO

CREATE TABLE [dbo].[BinaryContent](
    [BinaryContentID] [int] IDENTITY(1,1) NOT NULL
    , [FileName] [varchar](50) NOT NULL
    , [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]
    , [FileName] 
    , [BinaryContentRowGUID]
  , [FileContentBinary] = NULL
FROM
  [dbo].[BinaryContentTable];
GO

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

5

テーブルをFILESTREAM別のデータベースに分離PRODUCTIONし、ビューを使用してデータベースへの参照を作成できます。

これにより、ハッキングに頼ることなく、必要なことを実行できます。


これは私のアプローチになる予定だったが、私はその後、トリガーは、一般的にFILESTREAMテーブルではサポートされていないとして、データベース間の参照整合性を維持するための課題に直面してきた:dba.stackexchange.com/questions/58208/...
ジョン・J・スミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.