FILESTREAM verileri hariç veritabanını geri yükle


20

Bağlam
Altta büyük-ish veritabanına sahip bir sistem geliştiriyoruz. SQL Server 2008 R2 üzerinde çalışan bir MS SQL veritabanıdır. Veritabanının toplam boyutu yaklaşık 12 GB'dir.

Bunlardan yaklaşık 8,5 GB tek bir tabloda bulunuyor BinaryContent. Adından da anlaşılacağı gibi, bu, her türlü basit dosyayı doğrudan BLOB olarak tabloda sakladığımız bir tablodur. Son zamanlarda FILESTREAM kullanarak tüm bu dosyaları veritabanından dosya sistemine taşıma olasılığını test ediyoruz.

Veritabanımızda herhangi bir sorun olmadan gerekli değişiklikleri yaptık ve geçişten sonra sistemimiz hala iyi çalışıyor. BinaryContentTablo bu gibi kabaca görünür:

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]

Ayrı bir dosya grubundaki PRIMARYalan dışında her şey FileBinaryContentdosya grubunda bulunur FileStreamContentFG.

Senaryo
Bir geliştiricinin bakış açısından, en son verileri çalıştırabilmek için genellikle üretim ortamımızdan veritabanının yeni bir kopyasını isteriz. Bu durumlarda, BinaryContent'te saklanan dosyalarla nadiren ilgileniyoruz (şimdi FILESTREAM kullanılıyor).

Bu neredeyse istediğimiz gibi çalışıyor. Veritabanını şu şekilde dosya akışı olmadan yedekliyoruz:

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

Ve şu şekilde geri yükleyin:

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

Bu iyi çalışıyor gibi görünüyor ve FileBinaryContentalanı kullanan parçalardan kaçındığımız sürece sistemimiz çalışıyor . Örneğin, aşağıdaki sorguyu sorunsuz çalıştırabiliriz:

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

Doğal olarak, FileContentBinarysorguda dahil olmak üzere yukarıdaki satırın yorumunu kaldırırsam, bir hata alıyorum:

"Dbo.BinaryContent" tablosu için büyük nesne (LOB) verileri, erişilemeyen bir çevrimdışı dosya grubunda ("FileStreamContentFG") bulunur.

Sistemimiz içeriğin ayarlandığı dosyaları işler null, bu yüzden ne yapmak istiyorum böyle bir şey:

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

Ama bu elbette bana yukarıdaki ile aynı hatayı veriyor. Bu noktada sıkıştım.

Soru
Her şeyi FileStreamContentFGdosya grubundan geri yüklemek zorunda kalmadan veritabanını geri yükleyebilirim herhangi bir yolu var mı ? Yukarıda denediğim gibi değerleri null olarak veya dosya eksikse null olarak varsayılan olarak güncelleyerek?

Ya da soruna yanlış bir şekilde yaklaşıyor muyum?

Ben doğası gereği bir geliştiriciyim ve bir DBA olarak fazla bilgisi yok, bu yüzden burada önemsiz bir şey göz ardı edersem izin verin.


[BinaryContent] FILEGROUP'tan bazı verileriniz olması için tam geri yüklemeyi bir kez yapabilir ve güncelleştirmek istediğinizde Birincil dosya grubunun geri yüklemesini yapabilir misiniz?
jgardner04

@ jgardner04: bu işe yaramıyor. Ben ilk önce tam bir geri yükleme yaparsanız veritabanı tutarsız bir durumda sona erer, ardından yalnızca Birincil dosya grubunu içeren yedeklemenin geri yüklenmesi (Hata iletisi: "Günlük geri yüklenmediği için veritabanı kurtarılamaz (...) bir veya daha fazla RESTORE adımı gerektiğinden veritabanı çevrimiçi hale getirilemedi " ).
Julian

Dbo.BinaryContent'e erişiminiz her zaman saklı yordamlar yoluyla mıdır? Kaç kişi işin içinde?
Mark Storey-Smith

@ MarkStorey-Smith: veritabanına NHibernate (hem ASP.NET web uygulamasından hem de Windows form uygulamasından) üzerinden düzenli sorgular kullanılarak erişilir. Bu nasıl alakalı?
Julian

2
Erişiminiz saklı yordamlar üzerinden yapıldıysa, hangi dosya gruplarının çevrimiçi olduğunu kontrol etmek için kısmi kullanılabilirlik / parça parça geri yüklemeden bir yaklaşım uygulayabiliriz. Dürüst olmak gerekirse, 12GB'de sadece tam geri yükleme yapmak için etrafta çalışmaya değmez.
Mark Storey-Smith

Yanıtlar:


10

Yapmaya çalıştığınız şey veritabanını (işlemsel olarak) tutarsız bir durumda bırakacaktır, bu nedenle bu mümkün değildir.

Whitepaper Kısmi Veritabanı Durumu yararlı bir başvuru kılavuzu ve belirli bir tablo veya dosya çevrimiçi olup olmadığını kontrol etmek nasıl bir örnek içermektedir. Veri erişiminiz saklı prosedürlerden geçiyorsa, bu kontrolü nispeten kolayca dahil edebilirsiniz.

Senaryonuzda bir göz atmaya değer olabilecek alternatif (ama biraz hileli) bir yaklaşım, tabloyu gizlemek ve bir görünümle değiştirmek olacaktır.

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

Tabloyu FILESTREAMayrı bir veritabanında bir ile ayırabilir ve PRODUCTIONbir görünüm kullanarak veritabanında bir başvuru oluşturabilirsiniz .

Bu, hack'lere başvurmadan istediğinizi yapmanızı sağlar.


Bu benim yaklaşımım olacaktı, ama sonra tetikleyiciler genellikle filestream
John J Smith
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.