コンテキスト
大規模なデータベースが下部にあるシステムを開発しています。これは、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
に設定されているファイルを処理するため、likeを実行すると、次のようになります。
UPDATE [dbo].[BinaryContent]
SET [FileContentBinary] = null
しかし、もちろんこれは上記と同じエラーを私に与えます。この時点で私は行き詰まっています。
質問FileStreamContentFG
ファイルグループからすべてを復元することなくデータベースを復元する方法はありますか?上記のように値をnullに更新するか、ファイルが見つからない場合などにデフォルトでnullに更新しますか?
それとも私はおそらく間違った方法で問題に取り組んでいますか?
私は本質的に開発者であり、DBAとしての知識があまりないため、ここで些細なことを見落としている場合は失礼します。
あなたがしようとしていることは、データベースを(トランザクション的に)一貫性のない状態のままにするため、それは不可能です。
部分的なデータベースの可用性に関するホワイトペーパー は有用なリファレンスガイドであり、特定のテーブルまたはファイルがオンラインかどうかを確認する方法の例が含まれています。データアクセスがストアドプロシージャを介して行われた場合、そのチェックを比較的簡単に組み込むことができます。
シナリオで一見の価値がある1つの代替(ただし多少ハックな)アプローチは、テーブルを非表示にしてビューに置き換えることです。
-- 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
別のデータベースのFILESTREAM
を使用してテーブルを分離し、ビューを使用してPRODUCTION
データベースにテーブルへの参照を作成できます。
これにより、ハッキングに頼らずに、やりたいことができるようになります。