FILESTREAM डेटा को छोड़कर डेटाबेस पुनर्स्थापित करें


20

संदर्भ
हम नीचे में एक बड़े-ईश डेटाबेस के साथ एक प्रणाली विकसित कर रहे हैं। यह एक MS SQL डेटाबेस SQL ​​Server 2008 R2 पर चल रहा है। डेटाबेस का कुल आकार लगभग 12 जीबी है।

इनमें से, लगभग 8.5 जीबी एक ही तालिका में है 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

परिदृश्य
एक विकासकर्ता के दृष्टिकोण से, हम अक्सर अपने उत्पादन वातावरण से डेटाबेस की एक ताजा प्रति पसंद करते हैं, नवीनतम डेटा को काम करने में सक्षम होने के लिए। उन मामलों में, हम शायद ही कभी बाइनरीकॉन्टेंट (अब 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फ़ाइल समूह से सब कुछ बहाल कर सकता है ? या तो मैं ऊपर की कोशिश कर रहा हूँ के रूप में शून्य करने के लिए मूल्यों को अद्यतन करके, या फ़ाइल गायब है या कुछ और करने के लिए डिफ़ॉल्ट रूप से अशक्त करने के लिए?

या मैं शायद गलत तरीके से समस्या का सामना कर रहा हूं?

मैं स्वभाव से एक डेवलपर हूं और एक डीबीए के रूप में ज्यादा ज्ञान नहीं है, इसलिए मुझे बहाना करो अगर मैं यहां कुछ तुच्छ बात कर रहा हूं।


[बाइनरीकॉन्टेंट] FILEGROUP के कुछ डेटा होने के बाद क्या आप पूर्ण पुनर्स्थापना कर सकते हैं और जब आप इसे अद्यतित करना चाहते हैं तो प्राथमिक फ़ाइल समूह का पुनर्स्थापना करें?
jgardner04

@ jgardner04: यह काम नहीं करता है। डेटाबेस असंगत स्थिति में समाप्त होता है यदि मैं पहली बार पूर्ण पुनर्स्थापना करता हूं, इसके बाद केवल प्राथमिक फ़ाइल समूह (त्रुटि संदेश) के बैकअप को पुनर्स्थापित करने के बाद: "डेटाबेस को पुनर्प्राप्त नहीं किया जा सकता क्योंकि लॉग को पुनर्स्थापित नहीं किया गया था (...) डेटाबेस को ऑनलाइन नहीं लाया जा सकता है क्योंकि एक या एक से अधिक RESTORE चरणों की आवश्यकता है " )।
जूलियन

क्या आपकी पहुँच dbo.BinaryContent पर हमेशा संग्रहीत प्रक्रियाओं के माध्यम से होती है? कितने शामिल हैं?
मार्क स्टोरी-स्मिथ

@ MarkStorey-Smith: डेटाबेस को मुख्य रूप से NHibernate (ASP.NET वेब अनुप्रयोग और 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एक दृश्य का उपयोग करके डेटाबेस में इसका संदर्भ बना सकते हैं।

यह आपको वह करने की अनुमति देगा जो आप बिना हैक्स का सहारा लिए करना चाहते हैं।


यह मेरा दृष्टिकोण होने जा रहा था, लेकिन मैं तब डेटाबेस के बीच संदर्भात्मक
जॉन जे स्मिथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.