问题:我们使用了大量分布式事务,正研究数据库镜像以使我们的关键数据库之一具备高可用性。在测试过程中我们发现,在尝试对镜像数据库进行故障转移后,分布式事务有时会失败。能否说明这是为什么?
解答:这实际上是记录在案的使用分布式事务的限制。在使用数据库镜像或日志传送时会存在该限制,基本上对于在执行故障转移后 Windows 服务器名称会有所不同的任何技术,都存在该限制。
在使用 Microsoft 分布式事务处理协调器 (MSDTC) 事务时,本地事务处理协调器具有资源 ID,用于标识运行该协调器的服务器。在进行镜像故障转移时,主体数据库会承载于另一个服务器上(镜像伙伴),因此事务处理协调器的资源 ID 会有所不同。
如果某个分布式事务处于活动状态,镜像伙伴上的事务处理协调器会尝试识别该事务的状态,但是无法识别,因为它具有错误的资源 ID;MSDTC 无法识别该 ID,因为它最初未包含在该分布式事务中。在这种情况下,必须终止该分布式事务,这便是您所看到的行为。
跨数据库事务(涉及多个数据库中的更新的简单事务)也存在类似问题。如果所涉及的一个数据库进行了镜像,另外一个没有镜像,则跨数据库事务可以在这两个数据库中提交。如果进行强制镜像故障转移(当主体与镜像未同步,且执行允许丢失数据的手动故障转移时),在镜像数据库中提交的事务可能会丢失,这会破坏跨数据库事务的完整性。
这可能会在镜像数据库未同步时发生(有关详细信息,请参阅我发表的 2009 年 6 月专栏),因此提交的跨数据库事务的日志记录尚未发送到镜像。在强制故障转移后,新主体数据库中不存在该事务,因此会破坏跨数据库事务的完整性。
问题:最近我对某些性能计数器进行监视,以解决一个数据库存储方面的问题。在这个过程中,我注意到了一些非常奇怪的现象:尽管数据库中未进行任何操作,数据库文件仍然存在写入活动。数据和日志文件都存在这种情况。甚至在我确保未连接到 SQL Server 的情况下,这种情况仍在继续。既然没有连接,怎么会存在 I/O 活动呢?
解答:SQL Server 有很多需要运行的内部操作;这些操作称为后台任务。系统中会执行一个或多个后台任务,从而导致 I/O 活动。下面简单列出了可能的原因:
虚影清理:删除操作仅将记录标记为已删除,以优化取消操作时的性能;该操作实际上不对空间清零。一旦提交了删除操作,便必须执行某种操作,以从数据库中实际移除被删除的记录。这是由虚影清理任务完成的。有关详细信息,请参阅我的博客文章,这篇文章还说明了如何检查虚影清理任务是否正在运行。
自动缩减:启用此任务可以自动移除数据库中的空空间。此任务的工作方式是,将数据文件末尾的页面移动至开头,合并末尾的可用空间,然后截断文件。您当然可以启用此任务,但绝对不应这样做,因为这样会导致索引碎片问题(从而降低性能)并会占用大量资源。通常,还会为数据库启用自动增长,因此可能会陷入缩减-增长-缩减-增长的循环,这就做了大量无用功。您可以使用下面的查询检查所有数据库的状态:
- SELECT name, is_auto_shrink_on FROM sys.databases;
延迟丢弃:此任务负责执行丢弃或截断表和索引所需的工作(进行索引重新生成操作可能引起索引丢弃,即生成新索引,然后丢弃旧索引)。对于小型表和索引,会立即执行取消分配。对于较大的表和索性,会通过后台任务成批执行取消分配。这是为了确保获取所有必需的锁,而不致耗尽内存。您可以按照此处的联机丛书中所述,使用各种延迟丢弃性能计数器监视此任务。
延迟写入:此任务负责从内存中缓存(称为缓冲池)移除旧页面。当服务器内存不足时,即使对页面进行了更改,也可能必须将其移除。在这种情况下,更改过的页面必须先写入磁盘,之后才能从内存中移除。您可以按照此处的联机丛书中所述,使用“Lazy writes/sec”性能计数器监视此任务。
以上所有这些任务都可能对数据库进行更改。它们全都使用事务进行更改,只要提交事务,事务所生成的事务日志记录就必须写入磁盘上的数据库日志部分。因为会时常对数据库进行更改,所以还必须存在检查点,以将更改的数据文件页面刷新到磁盘。有关详细信息,请参阅我为 TechNet 杂志 2009 年 2 月刊撰写的文章了解 SQL Server 中的日志记录和恢复功能。
可以看到,不存在活动的 SQL Server 连接,不一定意味着进程处于静止状态,它可能正忙于执行一个或多个后台任务。如果所有数据库活动都完成很久后,I/O 活动仍在进行,可能还需要检查是否在运行计划作业。
问题:我是非自愿 DBA,正在尝试不同的任务以尽快熟悉工作。前任 DBA 设置作业将备份写入一个文件,但是我不知道如何还原这些备份。是否可以查看文件中的备份内容?我该如何正确地还原这些备份?
解答:尽管可以将备份附加到同一个文件,但是大多数人将每个备份放在名称有意义的(通常还带日期/时间戳组合)的独立文件中。这样有助于避免您所面临的问题,也便于执行其他任务:
每个备份都位于自己的文件中时,出于安全原因而复制备份会十分简单。如果所有备份都位于一个文件中,就只能通过复制整个备份文件来创建最新备份的副本。
当所有备份都位于一个文件中时,不能删除旧备份。
如果每个备份都有单独命名的文件,则不可能意外覆盖现有副本。
遗憾的是,这一点对您毫无帮助,您已在一个文件中包含多个备份。不过,可以通过两种方式还原副本:手动还原或使用 SQL Server Management Studio (SSMS) 还原。
若要查看文件中的备份内容,可以使用 SSMS 创建引用该文件的新备份设备。创建引用后,可以显示该备份设备中的内容的备份详细信息。也可以使用 RESTORE HEADERONLY 命令。这两种方法都会检查备份设备,并提供一行输出,用于描述文件中的每个备份。SSMS 使用友好名称标识备份类型。若要使用正确的语法,需要按照 SQL Server 联机丛书中有关该命令的条目(有关 SQL Server 2008 版本,请参阅此处)所提供的信息,确定每个备份的备份类型,从而可以使用适当的 RESTORE 命令还原备份。
您还需要确定要还原的备份。这有一点棘手,因为所需要的 RESTORE HEADERONLY 的输出列名称与您必须用于还原的选项不匹配。文件中的备份从 1 开始编号(1 表示最旧),在名为“Position”的列中可以找到编号。若要还原备份,必须在 RESTORE 命令的 WITH FILE=<编号> 部分中使用相应编号。下面是一个示例:
- RESTORE DATABASE test FROM DISK = 'C:\SQLskills\test.bak'
- WITH FILE = 1, NORECOVERY;RESTORE LOG test
- FROM DISK = 'C:\SQLskills\test.bak'
- WITH FILE = 2, NORECOVERY;
其他在此就不一一列举了。您必须从某个数据库备份开始还原序列,然后还原零个或多个差异数据库和/或事务日志备份。更详细的信息不在本专栏的讨论范围之内,不过,在我为 2009 年 11 月刊撰写的文章利用备份进行灾难恢复中,详细介绍了有关可能需要的还原序列和其他 RESTORE 选项。
使用 SSMS 时,可在还原数据库向导中指定备份文件,该向导会自动显示文件中的所有备份,并允许您选择需要的备份。图 1 显示了一个示例。
图 1 使用 SSMS 还原数据库向导显示文件中的多个备份。
无论选择哪个选项,在进行灾难恢复时,在正式执行还原之前,必须试还原到另一个位置,这一点至关重要。我始终遵循的原则之一是“没有成功还原,就没有备份。”
问题:我有一个很大的数据库,每隔几周就需要将它复制到开发环境中。我的问题是,最近数据库因要容纳更多数据增大了,现在将它还原到开发环境中时,它显得太大了。如何在还原该数据库时使它缩小一些?
解答:这是一个相当普遍的问题,遗憾的是,没有什么好的解决方法。
数据库备份不会以任何方式更改数据库,它仅仅读取所有已使用的数据库部分,将这些部分以及一些事务日志(有关原因和程度的说明,请参阅我的博客文章)包含在备份中。从数据库备份进行的还原仅创建文件,写出备份中的内容,然后对数据库运行恢复操作。基本上,数据库中的内容即是还原时获得的内容。没有选项可以用于在还原时缩减数据库、在还原时解决索引碎片问题、在还原时更新统计数据或是人们可能需要执行的任何其他操作。
那么,如何实现您的目的呢?根据具体方案,您有三种方法。
首先,可以对生产数据库执行缩减操作,以回收空的空间。这样可使还原的数据库副本与生产数据库相同,而不会浪费空间,但是成本可能会很高。生产数据库会再次增长,因而缩减操作可能成本极高(在 CPU、I/O 和事务日志方面),并可能导致索引碎片。索引碎片问题必须得到解决,从而会占用更多资源。您不会选择这么做。(有关使用数据文件缩减的风险的更深入说明,请参阅我的博客文章。)您可以考虑只移除文件末尾的可用空间 (DBCC SHRINKFILE WITH TRUNCATEONLY),但这可能不会达到您所希望的缩减大小。
其次,如果在开发过程中只需要还原一次生产数据库,则需要有足够空间来还原完整数据库,然后进行缩减以回收空间。在此之后,需要确定是否要解决缩减操作所产生的碎片。
如果要运行查询以进行性能测试或进行报告,碎片可能会极大降低这些查询的性能。如果不运行这类查询,则完全不必整理碎片。若要解决碎片问题,不能重新生成索引(使用 ALTER INDEX … REBUILD 命令),因为这需要额外空间并会导致数据库再次增大,您需要重新组织索引(使用 ALTER INDEX … REORGANIZE 命令)。
如果一定要整理碎片,请务必将数据库切换至 SIMPLE 恢复模型,以便事务日志不会因重新组织所生成的所有事务日志记录而增长。如果将数据库保留为 FULL 恢复模型,则日志会继续增长,除非您将日志备份(您可能希望避免处理这些内容)写入数据库的开发副本中。
最后,如果在开发过程中需要多次还原生产数据库,则不会希望多次重复第二种方法中的步骤。在这种情况下,最好按照第二种方法中的步骤执行,然后创建缩减(可能整理了碎片)数据库的另一个备份。
此第二个备份随后可以用于执行最小大小生产数据库的多次还原。
总而言之,要将拥有大量可用空间的生产数据库移动至开发环境,而不在初始还原时包括这些 SQL 可用空间,是无法实现的。
本文来源:微软TechNet中文站