SQL Server中的高可用性(2)----文件與文件組

    在談到SQL Server的高可用性以前,咱們首先要談一談單實例的高可用性。在單實例的高可用性中,不可忽略的就是文件和文件組的高可用性。SQL Server容許在某些文件損壞或離線的狀況下,容許數據庫依然保持部分在線,從而保證了高可用性。html

 

文件和文件組

    有關文件和文件組的基本概念,有不少文章已經闡述過了。這裏我只是提一下,文件組做爲SQL Server訪問文件的一個抽象層而存在。所以SQL Server上所作的操做不是直接針對文件,而是針對文件組。sql

    使用多個文件組和文件不只僅是爲了分散IO和提升性能,還有高可用性方面的緣由。有關一個數據庫應該包含幾個文件或文件組,Paul Randal已經作過很是棒的闡述,請參閱:http://www.sqlskills.com/blogs/paul/files-and-filegroups-survey-results/數據庫

    數據庫中使用多個文件或文件組在高可用性方面的好處包括:架構

  • 某文件的IO損壞,數據庫還能夠保證部分在線。
  • 將索引和表分開存放,假如索引文件不在線,數據依然能夠被訪問。
  • 歷史數據和熱數據分開,歷史歸檔數據損壞,不影響熱數據。
  • 分開數據文件使得在災難恢復時僅僅恢復部分數據從而縮短了宕機時間
  • 數據庫分爲多個文件使得能夠經過增長文件或移動文件的方式解決空間不足的問題

 

文件併發

    在SQL Server中,文件分爲三類,分別爲:ide

  • 主數據文件
  • 輔助數據文件
  • 日誌文件

    其中,主數據文件默認以擴展名mdf結尾,輔助數據庫文件默認以ndf結尾,日誌文件以ldf結尾。雖然擴展名是能夠修改的,但強烈建議不要去改擴展名。函數

    上面提到文件名值得是物理文件名,可是實際上在SQL Server中進行操做,操做的是邏輯文件名。高併發

    任什麼時候間,文件都會處於某一種狀態,這些狀態包括:sqlserver

  • 在線
  • 離線
  • 恢復中
  • 還原掛起
  • 質疑

    能夠經過sys.database_files這個DMV來查看數據庫文件中包含狀態在內的相關信息,如圖1所示。性能

    1

圖1.查看數據庫中文件的狀態等相關信息

 

   你甚至能夠在數據庫缺乏NDF文件時附加數據庫,具體細節,請參閱MCM黃大師的一篇文章:http://www.sqlnotes.info/2013/05/07/attach-database-with-missing-ndf-file/

 

文件組

    在SQL Server中,文件組中某個文件的狀態決定了整個文件組的狀態。但文件的狀態獨立於數據庫的狀態,好比說文件的狀態是離線,但數據庫依然能保證在線,這也就是所謂的數據庫部分在線,舉個例子,某個文件包含了名爲selldata的表,若是該文件離線,但數據庫在線,全部針對該selldata的表上的操做都會失敗。

   若是須要數據庫中的某個文件組在線,該文件組中的全部文件都應該處於在線狀態。

 

表分區

    表分區是自SQL Server 2005以後出現的一個概念,我以前已經寫過一篇關於表分區的文章。表分區的概念雖然很老了,可是不少地方對於表分區的使用依然處於很是初級的階段。

    我見過大部分想到使用表分區的例子是出現性能問題,從而考慮分散大表的IO。但實際上,表分區還會提升可用性。使用表分區的好處還包括:

  • 輕鬆管理大表或分區
  • 提升併發性(產生分區鎖,而不是表鎖)
  • 以文件組級別就行備份和還原,從而僅僅只備份和還原表的一部分(好比說只備份表中的熱數據),從而減小了還原時間
  • 能夠僅僅在線重建某個分區

 

    值得注意的是,對錶分區後,也要對錶上的非彙集索引進行索引分區。不然有可能形成性能方面的例子。

 

DEMO

DEMO1 :僅重建某個分區

    下面例子是一個簡單的分區表,並對索引進行分區後,僅僅重建某個分區,而不是整個索引。好比說表中按照數據冷熱進行分區,能夠僅僅對熱數據進行重建,從而大大減小了重建索引所需的時間,如代碼清單1所示。

--建立分區函數
CREATE PARTITION FUNCTION [t](int) AS RANGE LEFT FOR VALUES (100, 500)
--分區架構
CREATE PARTITION SCHEME [x] AS PARTITION [t] TO ([PRIMARY], [FileGroup1], [FileGroup1])

--建立表
CREATE TABLE [Sales].[SalesOrderDetailPartition](
	[SalesOrderID] [int] NOT NULL,
	[SalesOrderDetailID] [int] IDENTITY(1,1) NOT NULL,
	[CarrierTrackingNumber] [nvarchar](25) NULL,
	[OrderQty] [smallint] NOT NULL,
	[ProductID] [int] NOT NULL,
	[SpecialOfferID] [int] NOT NULL,
	[UnitPrice] [money] NOT NULL,
	[UnitPriceDiscount] [money] NOT NULL,
	[LineTotal]  AS (isnull(([UnitPrice]*((1.0)-[UnitPriceDiscount]))*[OrderQty],(0.0))),
	[rowguid] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
	[ModifiedDate] [datetime] NOT NULL,
) ON x(SalesOrderID)

INSERT 	INTO [Sales].[SalesOrderDetailPartition]([SalesOrderID],
	[CarrierTrackingNumber],
	[OrderQty] ,
	[ProductID] ,
	[SpecialOfferID],
	[UnitPrice],
	[UnitPriceDiscount],ModifiedDate,rowguid)
SELECT 	[SalesOrderID],
	[CarrierTrackingNumber],
	[OrderQty] ,
	[ProductID] ,
	[SpecialOfferID],
	[UnitPrice],
	[UnitPriceDiscount],ModifiedDate,rowguid FROM [Sales].[SalesOrderDetail]


go
--建立索引分區
CREATE NONCLUSTERED INDEX test_partition_idx ON [Sales].[SalesOrderDetailPartition](ProductID) on x(SalesOrderID)

--僅僅重建某個分區
ALTER INDEX test_partition_idx
ON [Sales].[SalesOrderDetailPartition]
REBUILD Partition = 1

   代碼清單1.僅僅重建某個分區,而不是整個索引

 

    關於這裏,更深刻的文章能夠參閱:http://www.mssqltips.com/sqlservertip/1621/sql-server-partitioned-tables-with-multiple-filegroups-for-high-availability/

 

DEMO2:數據庫部分在線和文件還原

--建立測試數據庫
CREATE DATABASE test
 GO
--改爲完整恢復模式
ALTER DATABASE test SET  RECOVERY FULL
--添加一個文件組
ALTER DATABASE test
ADD FILEGROUP WW_GROUP
 GO
 --向文件組中添加文件
ALTER DATABASE test
ADD FILE 
( NAME = ww,
FILENAME = 'D:\wwdat1.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB)
TO FILEGROUP ww_Group
 
 --在不一樣文件組上分別建立兩個表
CREATE TABLE test..test ( id INT IDENTITY )
ON  [primary]
CREATE TABLE test..test_GR ( id INT IDENTITY )
ON  ww_Group
 

--作完整備份
BACKUP DATABASE test
 TO DISK='D:\Test_backup.bak'WITH INIT

--作文件備份
BACKUP DATABASE test
    FILE = 'ww',
    FILEGROUP = 'ww_Group'
    TO DISK='D:\CROUPFILES.bak'WITH INIT
--備份日誌
BACKUP LOG test
    TO DISK='D:\Test__log.ldf'WITH INIT

 
--刪除文件組中的表內的數據
TRUNCATE TABLE test..test_GR

--還原備份,日誌僅僅被應用於那個還原狀態的文件
RESTORE DATABASE test
    FILE = 'ww',
    FILEGROUP = 'ww_Group'
    FROM DISK ='D:\CROUPFILES.bak'
    WITH FILE = 1,NORECOVERY
RESTORE LOG test
    FROM DISK='D:\Test__log.ldf'
    WITH FILE = 1, NORECOVERY

--備份尾端日誌
BACKUP LOG test
    TO DISK='D:\Test__log.ldf' WITH NOINIT,NO_TRUNCATE
--還原尾端日誌
RESTORE LOG test
    FROM DISK='D:\Test__log.ldf'
    WITH FILE = 2, RECOVERY
 GO

 --查看數據,刪除數據的操做被成功恢復
 SELECT  *
FROM    test..test_GR

--清除數據庫
DROP DATABASE test

   代碼清單2.備份還原單個文件

 

    代碼清單2很好的闡述了整個文件備份還原的過程,其中,在文件還原的過程當中咱們能夠看到數據庫自己是在線的,但數據庫中有一個文件處於還原狀態,如圖2所示。

2

圖2.ww文件處於還原中狀態

 

   此時對於表test_GR作操做的話,會提示因文件組沒有聯機而失敗,如圖3所示。

3

圖3.由於文件組沒有聯機而致使操做失敗

 

    再對尾端日誌進行備份還原以後,該文件組成功上線。

 

小結

    本篇文章闡述了文件和文件組在高可用性中的做用。瞭解這些特性對於下降還原時間很是有必要。在數據庫開始上線以前,儘可能合理的把一個數據庫分爲多個文件組和文件,不只僅提高性能和併發性,還可使得DR更加容易。

相關文章
相關標籤/搜索