首页SQLServerSQLSERVER备份与恢复 › 数据库备份与恢复 之四 选择数据库还原方案

数据库备份与恢复 之四 选择数据库还原方案

为了帮助用户能以最快的速度还原数据库,SQLServer也在不断引入新的还原方法。SQL Server一共可以支持4个级别的数据还原:

数据库(“数据库完整还原”)级

还原和恢复整个数据库。数据库在还原和恢复操作期间会处于离线状态。

数据文件(“文件还原”)级

还原和恢复一个数据文件或一组文件。在文件还原过程中,包含相应文件的文件组在还原过程中自动变为离线状态。访问离线文件组的任何尝试都会导致错误。但是其他文件组有可能还能保持在线。

数据页(“页面还原”)

在完整恢复模式或大容量日志恢复模式下,可以对数据库指定还原特定的一个或一些数据页面,而无须把整个数据库或整个文件都重新创建一遍。对于只损坏了很少一部分页面的大数据库,这种还原方式可以大大节约还原时间。

一部分(“段落还原”)

在大型数据库里,往往包含了若干个文件或文件组。使用段落还原,可以使数据库在还原了一部分文件或文件组以后,这部分数据就可以被访问,从而达到缩短数据库离线时间的目的。

但是SQL Server不允许用户备份或还原单个表。

SQL Server中的“还原方案”是指从一个或多个备份中还原数据,继而恢复数据库的过程。可选的还原方案取决于数据库的恢复模式和SQLServer的版本。

表9-3介绍了不同恢复模式所支持的各种还原方案。

表9-3  不同恢复模式所支持的各种还原方案

还原方案 在简单恢复模式下 在完整/大容量日志恢复模式下
数据库

完整还原

 这是基本的还原策略。

数据库完整还原可能涉及完整数据库备份的简单还原和恢复。另外,完整的数据库还原还可能涉及还原完整数据库备份,以及还原和恢复差异备份

 这是基本的还原策略。

数据库完整还原涉及还原完整数据库备份或差异备份(如果有),以及还原所有后续日志备份(按顺序)。通过恢复并还原上一次日志备份(RESTORE  WITH RECOVERY),完成数据库完整还原

文件还原*  只能还原损坏的只读文件,但不还原整个数据库。所以实用性不是很强  能够还原一个或多个文件,而不还原整个数据库。可以在数据库处于离线状态或数据库保持在线状态(对于SQL  Server 2005的某些版本)时执行文件还原。在文件还原过程中,包含正在还原的文件的文件组一直处于离线状态。其他文件组有可能被访问
页面还原  不适用  还原损坏的页面。可以在数据库处于离线状态或数据库保持在线状态(对于SQL  Server 的企业版)时执行页面还原。在页面还原过程中,正在还原的页面一直处于离线状态。

必须具有完整的日志备份链(包含当前日志文件),并且必须恢复所有这些日志备份,以使页面与当前日志文件保持一致

段落还原*  按文件组级别并从主文件组和所有读写辅助文件组开始,分阶段还原和恢复数据库  按文件组级别并从主文件组开始,分阶段还原和恢复数据库

* 只有SQL Server 企业版支持在线还原。

无论以何种方式还原数据,在恢复数据库前,SQLServer数据库引擎都会保证整个数据库在逻辑上的一致性。例如,还原一个文件以后,必须恢复完整的一套日志文件备份,以便将该文件里的事务前滚足够长度,与数据库保持一致,才能恢复该文件并使其在线。

下面我们从最传统的数据库完整还原开始,详细介绍SQLServer的主要还原方法。

数据库完整还原

将一个数据库从无到有,完整地还原出来,是最常使用的还原操作。在简单情况下,还原操作只需要一个完整数据库备份、一个差异数据库备份和后续日志备份。很容易构造一个正确的还原顺序。例如,若要将整个数据库还原到故障点,需要首先备份活动事务日志(日志的“尾部”)。然后,按备份的创建顺序还原最新的完整数据库备份、最新的差异备份(如果有)及所有后续日志备份。如果源数据库是简单模式,则没有相应的日志备份。恢复工作仅限于还原一个完整数据库备份,以及最后的一个差异备份。

在这种模式下,用户经常遇到的挑战,是发生灾难后如何将数据库恢复到一个特定的恢复点。例如,一个关键数据表被人在中午12点01分误删,如何将其恢复到12点钟的那个状态?

SQL Server能够很好地支持这类需求,可它是通过恢复日志文件到指定恢复点的方式来实现的。所以,它有几个先决要求。而且是要在灾难发生之前,数据库就必须满足以下所有条件:

(1)数据库的恢复模式必须是完整恢复模式。

(2)灾难发生前,数据库曾经做过一个完整数据库备份(或有一套完整的文件备份)。

(3)在上次完整数据库备份后,如果做过任何日志备份,这些日志备份现在每个都能找到。

符合这些要求的数据库,就可以使用备份恢复方法将数据库恢复到完整备份后的任意一个时间点。通常,将数据库恢复到故障点的基本步骤如下:

(1)备份活动事务日志(也称为日志尾部)。此操作将创建尾日志备份。如果活动事务日志在灾难发生后变得不可用,则该日志部分的所有事务都将丢失。

(2)还原最新完整数据库备份,而且不做事务恢复(RESTORE DATABASE database_nameFROM backup_deviceWITH NORECOVERY)。

(3)如果存在差异备份,则还原最新的差异备份,而不做事务恢复(WITHNORECOVERY)。

(4)从还原备份后创建的第一个事务日志备份开始,使用NORECOVERY依次还原日志。

(5)恢复数据库到某个时间点(RESTORE DATABASE database_name WITHSTOPAT='????????', RECOVERY)。此步骤也可以与还原上一次日志备份结合使用。

示例

AdventureWorks示例数据库在数据库备份之前已经设置使用完整恢复模式。下面的示例将创建AdventureWorks数据库的尾日志备份。接下来,将还原较早的完整数据库备份和日志备份,最后还原尾日志备份。事务恢复动作,将在最后的尾日志恢复步骤中完成。在此之前,数据库都不能被访问。

注意:在此示例之前,数据库已经做过一个数据库完整备份和一个日志备份。

 

--灾难发生后,试图创建一个尾日志备份

BACKUP LOG AdventureWorks

TO DISK = 'Z:\SQLServerBackups\AdventureWorks.bak'

WITH NORECOVERY;

GO

--从备份恢复一个全备份

RESTORE DATABASE AdventureWorks

FROM DISK ='Z:\SQLServerBackups\AdventureWorks.bak'

WITH FILE=1,

NORECOVERY;

 

--从备份中恢复一个正常的日志备份

RESTORE LOG AdventureWorks

FROM DISK ='Z:\SQLServerBackups\AdventureWorks.bak'

WITH FILE=2,

NORECOVERY;

 

--用STOPAT恢复尾日志备份

RESTORE LOG AdventureWorks

FROM DISK ='Z:\SQLServerBackups\AdventureWorks.bak'

WITH FILE=3, STOPAT='XXXXxx:xx:xx',

RECOVERY;

GO

上面的还原方案管理和执行都比较简单,是最广泛使用的还原方案。如果您的数据库不是超大数据库,这个方案就能够基本满足需求了。

可是这个方案的最大缺点就是要做一次数据库的完整备份恢复。这一步在时间和空间上,都是代价高昂的一步。

(1)在时间上,SQL Server需要很长的时间来重建整个数据库。而且在这个过程中,数据库都是不能访问的。时间的长短,基本由硬盘的速度决定。一个上TB的数据库,做一个完整恢复可能需要近一天的时间。这个等待时间,是很多系统不能接受的。

(2)在空间上,一个完整备份的大小和数据库已使用空间大小基本一致。如果备份是要放在硬盘上的,基本上就需要硬盘能提供2倍的空间。一份放数据库,一份放备份。

空间的问题大部分时候还能找到办法,可是时间上的等待往往让人难以接受。这时候数据库管理员可以根据灾难的严重程度,以及手里的备份文件,以及数据库的结构,看看是不是可以用下面这些比较不常用的还原方案。这些方案都需要数据库预先选择了完整恢复模式,操作起来比较复杂,但是如果用得好,能够大大缩短数据库离线时间。

文件还原

一个大数据库会有若干文件和文件组。如果损坏只是集中在其中一个文件或文件组上,而其他大部分的数据文件都没有损坏,使用传统的数据库还原方案将所有的文件重建,似乎有点浪费时间。如果SQLServer只是把坏掉的那个数据文件或者文件组重建,肯定能够省下来很多时间。

可是,数据库的事务修改是会分布在各个数据文件上的。如果用备份只恢复其中一个文件,而其他文件不恢复,那它们的状态一定会不一致。一定会有许多修改在被恢复的文件里没有被包含进来。这样的数据库是无法使用的。为了使新恢复的文件能够自动恢复备份以后做的修改,SQLServer需要借助事务日志。首先在恢复之前,必须做一次当前数据库的日志备份(即所谓的尾日志备份)。恢复所有日志备份,SQLServer就能利用前滚的方法将数据文件恢复到一致的时间点。

从文件备份和差异文件备份中还原一个或多个受损文件的步骤基本如下:

(1)创建活动事务日志的尾日志备份。

这一步是文件还原的至关重要的一步。对于离线文件还原,在文件还原之前必须始终先进行一次尾日志备份。对于在线文件还原,在文件还原之后必须始终先进行一次日志备份。此日志备份对于将文件恢复到与数据库的其余部分一致的状态至关重要。如果因为日志已损坏而无法执行此操作,则文件还原无法进行,必须还原整个数据库。

(2)从每个损坏的文件的最新文件备份还原相应文件。

(3)针对每个还原的文件,还原最近的差异文件备份(如果有)。

(4)按顺序还原事务日志备份,从覆盖最早还原文件的备份开始,到在步骤1中创建的尾日志备份结束。

虽然这里恢复的日志备份针对的是整个数据库,但是事务日志备份的恢复会是比较迅速的,因为这里仅处理对还原文件所做的更改。与还原整个数据库相比,这样做还是会节省很多时间。

下面举一个示例。一个名为adb的数据库(使用完整恢复模式)包含3个文件组。文件组A为读/写文件组,而文件组B和C是只读的。最初,所有文件组都处于在线状态。

现在文件组A中的文件a1已损坏,数据库管理员决定在数据库处于在线状态时还原该文件。

(1)在线还原文件a1。

RESTORE DATABASE adb FILE='a1' FROM backup WITH NORECOVERY

(2)此时,文件a1处于RESTORING状态,文件组A处于离线状态。

(3)完成文件还原之后,数据库管理员进行新的日志备份以确保捕获到该文件离线时的点。(之前曾经做过两次日志备份)

BACKUP LOG adb TO log_backup3WITH COPY_ONLY

(4)在线还原日志备份。

RESTORE LOG adb FROM log_backup1WITH NORECOVERY

RESTORE LOG adb FROM log_backup2WITH NORECOVERY

RESTORE LOG adb FROM log_backup3WITH RECOVERY

(5)文件a1现处于在线状态。数据库恢复完成。

页面还原

还有一种经常出现的情形,数据库发生了损坏,可是损坏不像前面那么严重。数据库的每个文件都能打开,只是其中的一些页面坏了。

这种情况可以借助DBCCCHECKDB来进行数据库修复。如果DBCC命令无法在不丢数据的前提下修复数据,或者哪怕是允许丢数据也修不好数据库,管理员只能做数据库完整恢复。为了少数几个页面而恢复整个数据库,代价可谓高昂。SQLServer 引入了一个页面还原的功能,可以只还原指定的若干页面,从而能够大大节省数据库恢复时间。可以说这是个能够救急的功能。

页面还原用于修复隔离的损坏页。还原和恢复少量页面的速度可能比还原一个文件更快,因此减少了还原操作中处于离线状态的数据量。然而,如果文件中要还原的不只是少量页面而是多数页面,则还原整个文件更为有效。例如,如果某个文件上的大量页都指出此文件有未解决的故障,不妨考虑直接还原该文件。

通常,要进行还原的页已经由于在访问该页时遇到错误而标记为“可疑”。可疑页在msdb数据库的suspect_pages表中进行了标识。可以立即还原多个数据库页。与9.3.2节里的文件还原一样,在页面还原后,也要恢复所有的日志文件备份。每次传递日志重做,前滚集都会前进一步。

需要注意的是,页面还原仅可以还原数据页。页面还原不能用于还原下列内容:

·        事务日志。

·        分配页:全局分配映射(GAM)页、共享全局分配映射(SGAM)页和页可用空间(PFS)页。这些系统页面损坏,页面还原无法恢复。

·        所有数据文件的页0(文件启动页)。

·        页1:9(数据库启动页)。

·        全文目录(Fulltext searchcatalog)。

页面还原还要符合下列要求:

·        数据库必须使用完整恢复模式。使用大容量日志恢复模式时可能不能成功。简单恢复模式无法使用这一功能。

·        只读文件组中的页面无法还原。

·        还原顺序必须从完整备份、文件备份或文件组备份中恢复页面开始。所以如果没有一份数据页面损坏之前做的备份,也无法进行还原。

·        页面还原需要截止到当前日志文件的连续日志备份,并且必须恢复所有这些日志备份后,页才能恢复到当前正常状态。所以如果数据库曾经做过截断日志动作,或者有份日志备份现在找不到了,那也无法进行页面恢复。

·        数据库备份和页面还原不能同时运行。

页面还原基本语法

若要在RESTOREDATABASE语句中指定一页,需要知道该页所在文件的文件ID和该页的页ID。所需语法如下:

RESTORE DATABASE database_name

   PAGE = 'file:page [ ,...n]' [ ,...n ]

FROM <backup_device> [ ,...n ]

WITH NORECOVERY

页面还原的过程

页面还原的基本步骤如下:

(1)获取要还原的损坏页的页ID。当SQL Server遇到校验或残缺写错误时,会返回页面编号,并将这些信息记录下来。可以通过查询msdb数据库里的suspect_pages表,或者监视事件和SQL Server errorlog文件里所报出的错误信息,查找损坏页的页ID。

(2)从包含页的完整数据库备份、文件备份或文件组备份开始进行页面还原。在RESTORE DATABASE语句中,使用PAGE子句列出所有要还原的页的页ID。

PAGE = 'file:page'

(3)应用最近的差异备份。

(4)应用后续日志备份。

(5)创建新的数据库尾日志备份。

(6)还原新的尾日志备份。应用这个新的日志备份后,就完成了页面还原,可以开始正常访问页面了。

示例

以下示例使用NORECOVERY还原文件B的4个损坏页。随后,将使用NORECOVERY应用两个日志备份,然后是尾日志备份(使用RECOVERY还原)。

此示例中,文件B的文件ID为1,损坏的页的页ID分别为57、202、916和1016。

RESTORE DATABASE <database> PAGE='1:57, 1:202, 1:916,1:1016'

FROM <file_backup_of_file_B>

WITH NORECOVERY;

RESTORE LOG <database> FROM <log_backup>

WITH NORECOVERY;

RESTORE LOG <database> FROM <log_backup>

WITH NORECOVERY;

BACKUP LOG <database> TO <new_log_backup>

RESTORE LOG <database> FROM <new_log_backup>WITH RECOVERY;

GO

段落还原

文件还原和页面还原适用于数据库损坏的范围比较小的情况,因为恢复时间比完整备份恢复短,所以可以大大缩短数据库恢复所造成的不可访问时间。但是如果数据库的损坏范围很大,可能跨越了若干个数据文件甚至文件组,这时候可能不得不恢复整个数据库。如果数据库很大,这段不可访问的时间就很长了。有时候一个大数据库有若干数据文件组,有些文件组里存放的是应用程序现在经常访问的数据,有些文件组存放的是历史数据,不经常访问。如果管理员能把应用经常访问的数据所在的文件组先恢复,数据库就恢复访问,那大部分应用程序就可以提前恢复正常。历史数据文件组可以在后台慢慢恢复。

为了满足这种需求,SQLServer提供了段落还原这种机制。段落还原包括从主文件组开始的一系列还原顺序,有时也可以从一个或多个辅助文件组开始。在还原顺序结束后,如果恢复的文件有效并且与数据库一致,则恢复的文件将能直接变为在线状态,恢复用户访问。

基本上所有版本的SQLServer 都支持离线段落还原。在SQL Server企业版中,段落还原还可以是在线的。离线和在线段落还原的含义如下:

n   离线段落还原方案

在离线段落还原中,数据库在部分还原顺序之后处于在线状态。尚未还原的文件组保持离线状态,而数据库必须进入离线状态后,才能继续还原没有还原的文件组。

n   在线段落还原方案

在进行在线段落还原时,数据库在完成部分还原顺序后,主文件组已经被恢复,它和所有其他已恢复的辅助文件组都处于可用状态,数据库进入在线状态,用户可以访问。尚未还原的文件组保持离线状态,而后面还原这些文件组时,数据库还能保持在线状态。

需要注意的是,如果仅还原了一部分文件组,则数据库和这些文件组有关的事务可能会被挂起,影响一部分数据页面的访问。这是正常现象,因为整个数据库必须一致。

无论数据库采用何种恢复模式,部分还原顺序都从RESTOREDATABASE语句开始,并且要指定PARTIAL选项。PARTIAL选项总是会启动一个新的段落还原,因此,在部分还原顺序的初始语句中,只能指定PARTIAL一次。当部分还原顺序完成并且数据库在线后,由于余下文件的恢复被推迟,这些文件的状态将变为“恢复已挂起”。

此后,管理员可以安排应用恢复数据库访问,而暂缓其他的文件组的还原。其他文件组还原的时候,不但要还原文件组备份,还要还原日志备份,以将文件组恢复到与数据库一致的点。

在简单恢复模式下,可以被推迟恢复的只有只读文件组。在完整恢复模式或大容量日志恢复模式下,任何包含多个文件组的数据库都可以使用段落还原,并且可以将数据库还原到任何时间点。段落还原的顺序如下:

1. 部分还原顺序。

部分还原顺序会还原主文件组和(可选的)部分辅助文件组。第一个RESTOREDATABASE语句必须执行以下操作:

·        指定PARTIAL选项。它表示段落还原的开始。

·        使用包含主文件组的任何完整数据库备份。常见的做法是通过还原部分备份来启动部分还原顺序。

·        若要还原到特定的时间点,必须在部分还原顺序中指定该时间。还原顺序的每个后续步骤都必须指定相同的时间点。

2. 文件组还原顺序会使其他文件组在线并处于与数据库一致的某个点。

在SQL Server 企业版中,当数据库在线时,可还原并恢复任何离线辅助文件组。如果特定只读文件未损坏且与数据库一致,则该文件无须还原。

如果在文件备份创建之前,只读文件组就已处于只读状态,则该文件组无须应用日志备份,并且文件还原会跳过日志备份的应用过程。如果文件组是读/写文件组,则必须将未中断的日志备份链应用于上一次完整还原或差异还原,文件组才能前进到当前的日志文件。

在下面的示例中,数据库adb将在发生灾难性事件后还原到一台新计算机。该数据库使用完整恢复模式,因此,开始进行还原之前必须先获取数据库的尾日志备份。发生灾难性事件前所有文件组都处于在线状态。文件组B是只读的。必须还原所有辅助文件组,但这些辅助文件组将按重要性顺序进行还原:A最高,其次是C,最后是B。在此示例中,存在4个日志备份,其中包括尾日志备份。

尾日志备份

在还原数据库之前,数据库管理员必须先备份日志尾部。由于数据库已损坏,因此创建尾日志备份要使用NO_TRUNCATE选项:

BACKUP LOG adb TO tailLogBackup WITH NORECOVERY, NO_TRUNCATE

尾日志备份是后面还原顺序中将要应用的最后一个备份。

还原顺序

(1)部分还原主文件组和辅助文件组A。

RESTORE DATABASE adb FILEGROUP='Primary' FROM backup1

WITH PARTIAL, NORECOVERY

RESTORE DATABASE adb FILEGROUP='A' FROM backup2

WITH NORECOVERY

RESTORE LOG adb FROM backup3 WITH NORECOVERY

RESTORE LOG adb FROM backup4 WITH NORECOVERY

RESTORE LOG adb FROM backup5 WITH NORECOVERY

RESTORE LOG adb FROM tailLogBackup WITH RECOVERY

此时,主文件组和辅助文件组A处于在线状态。文件组B和C中的所有文件都处于恢复挂起状态,这两个文件组处于离线状态。

步骤1中的最后一条RESTORE LOG语句的消息会指出:由于文件组C不可用,因此涉及此文件组的事务回滚已延迟。数据库可继续执行常规操作,但这些事务会在相应的页面上持有锁,阻止别人的访问和修改。

(2)在线还原文件组C。

在第二个还原顺序中,数据库管理员将还原文件组C,同时要把所有的日志备份再还原一遍:

RESTORE DATABASE adb FILEGROUP='C' FROM backup2a WITHNORECOVERY

RESTORE LOG adb FROM backup3 WITH NORECOVERY

RESTORE LOG adb FROM backup4 WITH NORECOVERY

RESTORE LOG adb FROM backup5 WITH NORECOVERY

RESTORE LOG adb FROM tailLogBackup WITH RECOVERY

(3)此时主文件组及文件组A和C处于在线状态。文件组B中的文件处于恢复挂起状态,该文件组处于离线状态。解析延迟的事务后,日志被截断。

(4)在线还原文件组B。

在第三个还原顺序中,数据库管理员将还原文件组B。文件组B的备份是在该文件组变为只读状态之后进行的,因此,在恢复过程中无须再恢复日志备份。

RESTORE DATABASE adb FILEGROUP='B' FROM backup2b WITHRECOVERY

(5)所有文件组现在都处于在线状态。

虽然段落还原的过程比较复杂,但是通过这样的还原顺序,管理员可以让最重要的文件组A提前交给用户使用。这个在灾难恢复时,其优势就非常大了。所以建议管理员还是要学会使用这种方式,以备不时之需。

还原方案小结

从上面的介绍可以看到,在备份文件相同的前提下,数据库管理员也可以根据具体情况选择不同的还原方案。传统的完全还原方案比较简单,易于操作,但是数据库离线的时间最长。后3种还原操作起来比较复杂,要求管理员对目标数据库的结构有详细了解。但是如果能够正确使用,能够大大缩短数据库离线时间。所以建议管理员可以预先针对自己的数据库,试验一下文件还原、页面还原和段落还原该怎么做,保留正确的脚本,有备无患。

文件还原、页面还原或段落还原的优点

只还原和恢复个别文件或页面(而非整个数据库)的方法具有以下优点:

·        还原少量数据,可以缩短复制和恢复数据的时间。

·        在SQL Server 企业版中,这种还原文件或页面的操作可能会允许数据库中的其他数据在还原操作期间仍保持在线状态,缩短数据库离线时间。

段落还原的方法具有以下优点:

·        能帮助让最重要的数据最先上线。

·        能允许在数据库恢复其他文件组的时候,先前已恢复的文件组仍保持在线状态。

恢复模式(Recovery Mode)和支持的还原操作

数据库的还原操作取决于其所用的恢复模式。表9-4简要说明了每种恢复模式是否支持给定的还原方案以及适用范围。

表9-4  每种恢复模式支持的还原方案以及适用范围

还原操作 完整恢复模式 大容量日志恢复模式 简单恢复模式
数据还原  完整还原(如果日志可用)  某些数据将丢失  自上次完整备份或差异备份后的任何数据将丢失
时点还原  日志备份所涵盖的任何时间  日志备份包含任何大容量日志更改时不允许  不支持
文件还原*  完全支持  不完全支持  仅对只读辅助文件可用
页面还原*  完全支持  不完全支持  无
段落还原*  完全支持  不完全支持  仅对只读辅助文件可用

* 仅适用于SQL Server企业版。

9.3.6 孤立用户故障排除

有时候管理员需要将一个用户数据库从一台SQLServer使用备份和恢复的方式迁移到另一台服务器。数据库恢复以后,系统管理员可以正常看到里面所有的数据。可是原先用户定义的一些其他数据库用户,却可能无法继续在新的服务器上使用。尤其对一些SQLServer账号,哪怕在新服务器上手工创建了它们,还是不能正常地映射到数据库用户上。这是为什么呢?

SQL Server的用户安全管理分两层,整个服务器一层,每个数据库一层。一个用户,在每一层上都有账号,在两个层面上都会分配不同的权力。在服务器层的账号,叫登录账号(Login),可以设置它管理整个SQL Server服务器,开启跟踪,修改SQLServer安全配置,备份所有数据库等。在数据库一层,叫数据库用户(Database User),可以设置它对这个特定的数据库有读写、修改表格结构、存储过程定义等权限。

所以服务器层面的安全,是设置在服务器的登录账号上的。所有登录账号的信息,存放在master数据库里。可以查询master数据库里的sys.server_principals这张视图。每个登录账号都有一个唯一编号SID。对于一个WindowsLogin,它的SID就是Windows用户在域里的SID,SQL Server不会做改变。对于SQLLogin,除了它的名字,SQL Server还会在创建的时候给它随机生成一个SID。一样的名字,每次生成的SID都有可能不一样。

数据库层面有“数据库用户”这个概念。每个数据库内部对象的安全性,例如表格的读写,是否能运行或修改存储过程等,都赋予在数据库用户上,保存在这个数据库内部。可以通过查询sys.database_principals了解用户信息。每个数据库用户除了名字,也有一个唯一的SID。

SQL Server登录账户必须要和某个数据库用户相对应后,才能被数据库接纳。这个对应,就是要使得用户数据库sys.database_principals里的SID和master数据库sys.server_principals里的SID匹配起来。一个登录账户和数据库用户的名字可以不一样,但是SID必须一样。

对于Windows登录账号,如果新的服务器和原先的服务器在同一个域里,那么同样的Windows登录账号会有一样的SID。用户数据库恢复在新服务器以后,只需将Windows登录账号加入SQLServer。因为两个SID值是一样的,sys.database_principals里的数据库用户和master数据库sys.server_principals里的登录账号可以自动匹配,Windows登录账号可以自动继续使用用户数据库。

对于SQL登录账号就有问题了。假设在原先的服务器上有一个SQL登录账号名叫“test”,它对应于用户数据库里的用户“test”。在sys.database_principals里的SID和master数据库sys.server_principals里的SID是相同的。当“test”登录SQLServer后,可以被映射到数据库用户“test”,拥有它上面所赋予的权限。

当用户数据库恢复到新的服务器上后,master数据库sys.server_principals里并没有这个账号。但是用户数据库里还是有“test”这个数据库用户。于是这个用户被“孤立”了。

若要检测孤立用户,可以执行下列Transact-SQL语句:

USE <database_name>;

GO;

sp_change_users_login @Action='Report';

GO;

输出中列出了当前数据库中未链接到任何SQLServer登录名的用户以及相应的安全标识符(SID)。

这时要首先在SQL Server服务里加入“test”这个SQL登录账号。可是,新服务器为这个SQL登录账号所生成的SID是随机产生的,和原先服务器上的值会不一样。这个“test”服务器登录账户还是不能使用数据库。管理员还要用以下命令重新链接“test”服务器登录账户与数据库用户“test”,将它们的SID改成一致。

USE <database_name>;

GO

sp_change_users_login@Action='update_one',@UserNamePattern='<database_user>',@LoginName='<login_name>';

GO

需要说明的是,sp_change_users_login只能重新链接SQL登录账号。对于数据库用户所对应的是Windows登录账号,如果SID不同,说明域也发生了变化。SQL Server认为这两个Windows登录账号不是同一个。Windows服务器登录账户和数据库用户是不能强制链接在一起的。

如果一个数据库里有成百上千的数据库用户,这样的手工操作会是个费时费力的过程。如果我们能将master数据库与用户数据库一起恢复在新服务器上,两边的SID就还能保持一致,管理员就无须做这些额外的事情。这也是强调要备份系统数据库的原因之一。

转载本站文章请注明出处:就是他吧 http://www.94taba.com/?p=172

上一篇:

下一篇: