Khôi phục cơ sở dữ liệu không bao gồm dữ liệu FILESTREAM


20

Bối cảnh
Chúng tôi đang phát triển một hệ thống với cơ sở dữ liệu lớn ở phía dưới. Nó là một cơ sở dữ liệu MS SQL chạy trên SQL Server 2008 R2. Tổng kích thước của cơ sở dữ liệu là khoảng 12 GB.

Trong số này, khoảng 8,5 GB nằm trong một bảng BinaryContent. Như tên cho thấy, đây là một bảng nơi chúng tôi lưu trữ các tệp đơn giản, dưới bất kỳ hình thức nào, trực tiếp trong bảng dưới dạng BLOB. Gần đây, chúng tôi đã thử nghiệm khả năng di chuyển tất cả các tệp này ra khỏi cơ sở dữ liệu vào hệ thống tệp bằng cách sử dụng FILESTREAM.

Chúng tôi đã thực hiện các sửa đổi cần thiết cho cơ sở dữ liệu của mình mà không gặp sự cố nào và hệ thống của chúng tôi vẫn hoạt động tốt sau khi di chuyển. Các BinaryContentbảng trông gần như thế này:

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]

Với mọi thứ nằm trong PRIMARYnhóm tệp, ngoại trừ trường FileBinaryContentnằm trong nhóm tệp riêng biệt FileStreamContentFG.

Kịch bản
Từ quan điểm của một nhà phát triển, chúng tôi thường muốn có một bản sao mới của cơ sở dữ liệu từ môi trường sản xuất của chúng tôi, để có thể làm việc với dữ liệu mới nhất. Trong những trường hợp đó, chúng tôi hiếm khi quan tâm đến các tệp được lưu trữ trong BinaryContent (hiện đang sử dụng FILESTREAM).

Chúng tôi có điều này gần như làm việc như chúng tôi muốn. Chúng tôi sao lưu cơ sở dữ liệu, không có luồng tệp như thế này:

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

Và khôi phục nó như thế này:

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

Điều này có vẻ hoạt động tốt, và hệ thống của chúng tôi hoạt động miễn là chúng tôi tránh các phần sử dụng FileBinaryContenttrường. Ví dụ, chúng tôi có thể chạy truy vấn sau mà không gặp sự cố:

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

Đương nhiên, nếu tôi không bình luận dòng trên, bao gồm FileContentBinarytrong truy vấn, tôi gặp lỗi:

Dữ liệu đối tượng lớn (LOB) cho bảng "dbo.BinaryContent" nằm trong nhóm tệp ngoại tuyến ("FileStreamContentFG") không thể truy cập được.

Xử lý hệ thống của chúng tôi các file mà nội dung được thiết lập để null, vì vậy những gì tôi sẽ thích làm là một cái gì đó như thế này:

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

Nhưng điều này tất nhiên mang lại cho tôi lỗi tương tự như trên. Tại thời điểm này tôi bị mắc kẹt.

Câu hỏi
Có cách nào để tôi có thể khôi phục cơ sở dữ liệu mà không phải khôi phục mọi thứ từ FileStreamContentFGnhóm tệp không? Hoặc bằng cách cập nhật các giá trị thành null khi tôi đang thử ở trên hoặc mặc định thành null khi tệp bị thiếu hoặc một cái gì đó?

Hay có lẽ tôi đang tiếp cận vấn đề một cách sai lầm?

Bản chất tôi là một nhà phát triển và không có nhiều kiến ​​thức như một DBA, vì vậy, xin lỗi nếu tôi đang xem xét một số điều tầm thường ở đây.


Bạn có thể thực hiện khôi phục hoàn toàn một lần để bạn có một số dữ liệu từ [BinaryContent] FILEGROUP và sau đó thực hiện khôi phục nhóm fileg chính khi bạn muốn cập nhật nó không?
jgardner04

@ jgardner04: điều đó dường như không hoạt động. Cơ sở dữ liệu kết thúc ở trạng thái không nhất quán nếu trước tiên tôi thực hiện khôi phục hoàn toàn, sau đó là khôi phục bản sao lưu chỉ chứa nhóm tệp Chính (Thông báo lỗi: "Cơ sở dữ liệu không thể được khôi phục do nhật ký không được khôi phục (...) cơ sở dữ liệu không thể được đưa trực tuyến vì cần một hoặc nhiều bước RESTORE " ).
Julian

Bạn có quyền truy cập vào dbo.BinaryContent luôn thông qua các thủ tục được lưu trữ không? Có bao nhiêu người tham gia?
Mark Storey-Smith

@ MarkStorey-Smith: cơ sở dữ liệu chủ yếu được truy cập bằng các truy vấn thông thường, thông qua NHibernate (cả từ ứng dụng web ASP.NET và ứng dụng biểu mẫu Windows). Làm thế nào là có liên quan?
Julian

2
Nếu quyền truy cập của bạn là thông qua các thủ tục được lưu trữ, chúng tôi có thể áp dụng cách tiếp cận từ khôi phục sẵn có / từng phần để kiểm tra xem các nhóm nào đang trực tuyến. Thành thật mà nói, ở mức 12 GB, nó thực sự không đáng để làm việc, chỉ để thực hiện khôi phục hoàn toàn.
Mark Storey-Smith

Câu trả lời:


10

Những gì bạn đang cố gắng làm sẽ khiến cơ sở dữ liệu ở trạng thái không nhất quán (giao dịch), do đó không thể thực hiện được.

Bảng trắng sẵn có của Cơ sở dữ liệu một phần là một hướng dẫn tham khảo hữu ích và bao gồm một ví dụ về cách kiểm tra xem một bảng hoặc tệp cụ thể có trực tuyến hay không. Nếu truy cập dữ liệu của bạn thông qua các thủ tục được lưu trữ, bạn có thể dễ dàng kết hợp kiểm tra đó.

Một cách tiếp cận khác (nhưng hơi khó hiểu) có thể đáng xem trong kịch bản của bạn sẽ là ẩn bảng và thay thế nó bằng một khung nhìn.

-- 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

Bạn có thể cô lập bảng với một FILESTREAMcơ sở dữ liệu riêng biệt và tạo một tham chiếu đến nó trong PRODUCTIONcơ sở dữ liệu bằng cách sử dụng một khung nhìn.

Điều này sẽ cho phép bạn làm những gì bạn muốn mà không cần phải dùng đến hack.


Đây sẽ là cách tiếp cận của tôi, nhưng sau đó tôi đã đưa ra các vấn đề về duy trì tính toàn vẹn tham chiếu giữa các cơ sở dữ liệu, vì các trình kích hoạt thường không được hỗ trợ với các bảng filestream: dba.stackexchange.com/questions/58208/ Khăn
John J Smith
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.