FILESTREAM 데이터를 제외한 데이터베이스 복원


20

컨텍스트
맨 아래에 데이터베이스가 큰 시스템을 개발 중입니다. SQL Server 2008 R2에서 실행되는 MS SQL 데이터베이스입니다. 데이터베이스의 총 크기는 약 12GB입니다.

이 중 약 8.5GB가 단일 테이블에 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 (Large Object) 데이터는 액세스 할 수없는 오프라인 파일 그룹 ( "FileStreamContentFG")에 있습니다.

우리의 시스템 핸들 컨텐츠로 설정 파일 null내가 될지, 그래서 좋아 할이 같은 것입니다 :

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

그러나 이것은 물론 위와 같은 오류를줍니다. 이 시점에서 나는 붙어 있습니다.

질문 파일 그룹
에서 모든 것을 복원하지 않고도 데이터베이스를 복원 할 수있는 방법이 FileStreamContentFG있습니까? 위에서 시도한 것처럼 값을 null로 업데이트하거나 파일이 없거나 다른 것이 있으면 기본값을 null로 설정합니까?

아니면 잘못된 방법으로 문제에 접근하고 있습니까?

나는 본질적으로 개발자이며 DBA에 대한 지식이 많지 않으므로 여기서 사소한 것을 간과하고 있다면 실례합니다.


전체 복원을 한 번 수행하여 [BinaryContent] FILEGROUP의 일부 데이터를 보유한 다음 업데이트하려는 기본 파일 그룹을 복원 할 수 있습니까?
jgardner04

@ jgardner04 : 작동하지 않는 것 같습니다. 전체 복원을 먼저 수행 한 다음 기본 파일 그룹 만 포함하는 백업을 복원하면 데이터베이스가 일관성이없는 상태가됩니다 (오류 메시지 : "로그가 복원되지 않아서 데이터베이스를 복구 할 수 없습니다 (...) 하나 이상의 RESTORE 단계가 필요하므로 데이터베이스를 온라인 상태로 만들 수 없습니다 " ).
율리우스

저장 프로 시저를 통해 dbo.BinaryContent에 항상 액세스 할 수 있습니까? 얼마나 많은 사람이 참여하고 있습니까?
Mark Storey-Smith

@ MarkStorey-Smith : 데이터베이스는 주로 ASP.NET 웹 응용 프로그램 및 Windows Forms 응용 프로그램에서 NHibernate를 통해 일반 쿼리를 사용하여 액세스합니다. 그것은 어떻게 관련이 있습니까?
율리우스

2
저장 프로 시저를 통해 액세스 한 경우 부분 가용성 / 조각 복원 방식을 적용하여 온라인으로 파일 그룹을 확인할 수 있습니다. 솔직히 말하면 12GB에서는 전체 복원을 수행하는 것이 실제로 가치가 없습니다.
Mark Storey-Smith

답변:


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하고 뷰를 사용하여 데이터베이스에서 테이블에 대한 참조를 작성할 수 있습니다.

이를 통해 해킹에 의존하지 않고 원하는 것을 할 수 있습니다.


이것은 나의 접근 방식이 될 것이지만, 트리거는 일반적으로 파일 스트림 테이블에서 지원되지 않기 때문에 데이터베이스 간 참조 무결성을 유지하는 문제에 대해 제기했습니다. dba.stackexchange.com/questions/58208/…
John J Smith
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.