SQL问答:损坏恢复提示、压缩建议

日期: 2010-12-07 作者:Paul S. Randal 来源:TechTarget中国

  问题:我使用的备份策略是在每天的凌晨 1 点钟进行一次完整备份,每一小时进行一次日志备份,同时,在每天的凌晨 4 点钟会运行一次 DBCC CHECKDB。如果我在上午 8 点开始工作时发现,夜间运行的一致性检查报告了大量损坏的情况,我该如何进行恢复才不会丢失太多数据?

  解答:这取决于损坏发生的时间、损坏的内容以及您所采取的备份措施。理想情况是您事先已制定了灾难恢复计划,因而知道接下来应该怎么操作。不过,我会将您的问题当作假设性问题进行回答。

  根据您的描述,损坏的情况是在完整数据库备份完成后通过运行 DBCC CHECKDB 发现的,据此很难判断是在数据库备份之前还是之后出现的损坏。如果是在数据库备份之前的某段时间出现了损坏的情况,则备份中包含已损坏的数据库版本,因此恢复过程将更加复杂。

  首先要做的是在其他位置还原最近的数据库备份,并对其运行 DBCC CHECKDB。如果未发现损坏情况,请按以下步骤进行还原,这样应该不会丢失任何数据:

  · 运行损坏数据库的日志尾部备份(以捕获最近的事务)。

  · 还原最近的完整数据库备份,指定 WITH NORECOVERY。

  · 使用 WITH NORECOVERY 依次还原自完整数据库备份以来的所有事务日志备份以及日志尾部备份。

  · 使用命令 RESTORE databasename WITH RECOVERY 完成还原过程。

  最后,您应该再运行一次 DBCC CHECKDB 以确保不再存在损坏的内容,然后在第一时间执行根源分析以找出导致损坏的原因,并采取措施解决此问题。

  如果在执行了上述还原步骤后仍存在损坏的内容,则说明某个事务日志备份中可能包含损坏的内容,也可能是内存中包含损坏的内容,随后这些内容被记录到了事务日志中。如果是这种情况,您可能需要执行时间点还原,以确定损坏出现的时间并在此时间之前停止还原。此步骤超出了本专栏的讨论范围,但在联机丛书中对此有详细介绍。

  如果最近的数据库备份确实包含损坏的内容,您可能需要按照上述步骤进行操作,但要从下一个最近的完整数据库备份开始。此操作假定您仍保有此完整数据库备份和所有干预日志备份。

  另一种可用策略(您可能必须采用以适应允许的最长停机时间或恢复时间目标的限制)是手动或使用 DBCC CHECKDB 中的修复功能删除损坏的数据,然后尝试从较早的一系列备份中恢复一些数据。

  从损坏中进行恢复可能非常容易,也可能非常困难,具体取决于错误的根源以及您可以采取的措施。在接下来的几个月内,我将会在几篇文章中对此进行阐述。

  问题:我们的开发团队打算构建一个采用 SQL Server 2008 的更改跟踪功能的解决方案。根据相关文档的说明,我们可能需要针对相关的数据库启用快照隔离,但我担心这样会影响数据库的性能。您对此有何评论?

  解答:我在 2008 年 11 月这一期的杂志(“跟踪企业数据库中的更改”)中对更改跟踪进行了说明,对于您的问题,答案是肯定的,您需要启用行版本控制。这是因为检索已更改数据的机制通常如下:

  查询更改跟踪系统以找出更改的表格行。

  查询表格以检索已更改的行。

  在没有任何行版本控制机制的情况下,如果在执行查询的过程中运行更改跟踪清理任务,则首次查询可能会返回无效结果。而在执行第二次查询前,如果首次查询的结果中引用的一些表格行被删除,则第二次查询可能会失败。

  保持稳定性的一种做法是锁定更改跟踪数据和必需的用户表,但这样会导致并发性能变差(因为阻止的原因)和工作负载吞吐量降低。另一种保持稳定性的做法是使用快照隔离。

  快照隔离有两种,一种是在事务级别提供一致性(数据库选项:allow_snapshot_isolation),另一种是在 T-SQL 语句级别(数据库选项:read_committed_snapshot)提供一致性。事务级别的选项要求正确使用更改跟踪,这种选项简称为快照隔离。

  快照隔离可保持表格记录的版本,举例来说,某个显式事务启动后,从其启动的时间点开始,该事务肯定可以看到数据库的一致的时间点视图。要使用更改跟踪,上述两次查询都应纳入单个显式事务中,隔离级别应设为快照;这样就可以保证一致性。

  我的妻子 Kimberly 在其白皮书“SQL Server 2005 快照隔离”中对快照隔离作了详细的介绍。

  使用快照隔离时,可能会出现两种性能问题。第一种性能问题是,对数据库中的所有表格进行的所有更新都必须生成更改记录版本,即使版本从未使用过也是如此。记录的预更改版本必须被复制到版本存储区中,同时新的记录包含指向较早记录的链接,这是为了应对在此事务完成之前,另一事务启动并需要正确的记录版本的情况。这为所有更新操作都增加了一些处理开销。

  第二种性能问题是,版本存储区位于 tempdb 数据库内。对某些 SQL Server 实例而言,Tempdb 可能是最繁忙的数据库,因为它供所有连接和数据库共享。一般而言,tempdb 可能是一个性能瓶颈,即使不使用行版本控制也是如此。添加行版本控制意味着向 tempdb 增加更多压力(体现在使用的空间和 I/O 操作上),从而可能导致常规的工作负载吞吐量下降。

  您可以阅读白皮书“使用 SQL Server 2005 中的 tempdb”了解更多相关内容。虽然这里提到的两本白皮书都是针对 SQL Server 2005 撰写的,但它们同样适用于 SQL Server 2008。

  问题:DBCC CHECKDB 会全面检查数据库中的所有内容吗?有人说不会。另外,修复系统能修复所有问题吗?同样有人说不能。如果 DBCC CHECKDB 的检查和修复并不全面,我该怎么做?

  解答:该工具的检查和修复可以说是全面的,也可以说是不全面的!DBCC CHECKDB 可提供一组全面的一致性检查,而随着其版本的不断更新,其检查功能还在不断增强。不过,也有一些方面是该工具无法检查的。

  简单来说,该工具可以:

  ·检查系统目录的一致性

  ·检查分配元数据的一致性

  ·检查所有用户表的一致性

  本解答不提供有关运行哪些检查的更详细的说明(您可以访问我的博客或阅读最近的 SQL Server 2008 Internals 一书了解详情),但所用的每个数据库页至少会被读入内存并验证。这样可以找出由 I/O 子系统中的错误导致的常见损坏(约 99.99% 的损坏都是这样产生的)。

  在任何版本的 SQL Server 中都不会被检查的两个最常见的项目是,存储在数据库中的列内容和索引键值统计信息,不过,在今后的版本中,我们可能会添加对这两个项目和约束有效性(举例来说,表格之间的外键约束)的检查。约束有效性可单独使用 DBCC CHECKDB 的 DBCC CHECKCONSTRAINTS 命令检查,实际上,如果您必须在包含约束的数据库中运行修复操作,则建议您以后再验证约束的有效性,这是因为修复操作不会考虑约束,并可能会意外使其无效。这些内容都可以在联机丛书中找到。

  修复系统无法修复所有问题。在合理的时间内,此工具可能无法保证彻底修复某些错误。此类损坏很少,我的博客文章“CHECKDB From Every Angle:Can CHECKDB Repair Everything?”对此进行了说明,举例来说,如果在系统目录中有一个损坏的页面,则可采取的修复措施只能是删除此页面。不过,如果该页面存储了数据库中某些用户表的元数据,那该怎么办?删除该页面也就意味着删除这些用户表,因此不能进行修复。

  大部分修复操作都会导致某些数据丢失(因为这是在合理的时间内保证正确修复损坏的唯一途径),因此,在执行灾难恢复时,不到万不得已请勿使用修复操作。使用全面备份策略中的备份是避免丢失数据的唯一途径(除非维护了某些格式的同步副本)。

  DBCC CHECKDB 功能非常全面,可以检测到破坏性损坏,为确保在第一时间发现损坏的内容,应将定期运行 DBCC CHECKDB 作为数据库维护策略的一部分(参见我的博客文章“Importance of Running Regular Consistency Checks”)。没有任何工具可以解决一切问题,不过,如果您确保针对所有数据库启用页面校验和,则可以使 DBCC CHECKDB 发挥更大的作用,同时可使 SQL Server 检测到在 SQL Server 内存之外更改数据库页的时间。

  问题:我对压缩操作感到困惑。在我阅读过的相关文章中,关于压缩数据文件的操作是好还是坏,说法不一。我在查找有关压缩日志文件的相关信息时也遇到了这种问题。到底是怎么回事?

  解答:压缩操作的确非常容易让人产生误解,而数据文件压缩和日志文件压缩之间的差异是导致这些误解的重要原因。

  针对数据文件的压缩操作是为了将距离文件末尾最近的数据库页移到文件的开头部分。这样会导致数据文件的末尾部分产生“空白”区域,这些区域可以返还 OS。换句话说,数据文件从物理角度而言变小了。

  另一方面,针对事务日志文件的压缩操作不会移动任何内容,只要事务日志记录没有因为任何原因被保留,该操作就只会删除文件末尾的事务日志的空白区域。如果操作成功,日志文件从物理角度而言会变小。

  用户的困惑主要集中在这两种操作的副作用以及何时执行上。

  用户有时会被建议(或自行决定)压缩数据文件以回收空间,这可能是因为其索引维护操作导致数据文件增大,或者其驱动器空间不足,面对这种情况,用户自然会想到回收这样的一些“被浪费”的空间。不过,数据文件可能会再次用到这些空间,因此,通常情况下,最好将剩余的空闲空间保留供数据文件使用,而不要重复地压缩文件并使文件自动增长。

  压缩数据文件的副作用非常严重,因此应尽量避免使用此操作。压缩数据文件会导致大量索引碎片的产生,因此可能会影响查询的性能。我的博客文章“Why You Should Not Shrink Your Data Files”中提供了一段简单的脚本来说明这种情况。

  我在这篇博客文章中还阐述了何时可以压缩数据文件(几乎没有合适的时间)以及可以避免产生碎片副作用的其他方法。遗憾的是,我见过许多未提及相关的副作用就推荐用户执行数据文件压缩的情况。

  与压缩数据文件相比,压缩日志文件的操作更应该慎之又慎。通常情况下,由于用户采用的文件大小管理方法不当,导致日志文件过大且与数据文件大小相比极不均衡,因此用户希望压缩日志文件,或者是因为用户看到日志文件变大而希望将其控制在尽可能小的范围内。主动数据库的日志文件需要保持合理的大小,但应对日志进行管理,以保证无需对其进行压缩,并无需使其增大以应对数据库中的活动。

  您可以阅读我为 2009 年 2 月那一期杂志撰写的文章“Understanding Logging and Recovery”了解有关事务日志的详情。我还写过一篇阐述如何管理事务日志大小的博客文章,请参阅“Importance of Proper Transaction Log Size Management”。

  最低要求是尽可能少地进行任何形式的压缩操作,如果确定采取压缩操作,应确保完全理解其可能造成的后果。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

相关推荐