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更加容易。

相关文章
相关标签/搜索