排查 DBCC CHECKDB 报告的数据库一致性错误

本文介绍如何排查由 DBCC CHECKDB 命令报告的错误。

原始产品版本: SQL Server
原始 KB 数: 2015748

现象

当执行 DBCC CHECKDB(或其他类似命令,如 DBCC CHECKTABLE)时,会向 SQL Server 错误日志写入如下消息:

DBCC CHECKDB (mydb) executed by MYDOMAIN\theuser found 15 errors and repaired 3 errors.
Elapsed time: 0 hours 0 minutes 0 seconds.
Internal database snapshot has split point LSN = 00000026:0000089d:0001 and first LSN = 00000026:0000089c:0001.
This is an informational message only. No user action is required.

如果使用了修复选项,则此消息显示找到的数据库一致性错误数以及修复了多少个错误。 此消息还作为包含 EventID=8957 的信息级别消息写入 Windows 应用程序事件日志。 即使报告了错误,此消息也是信息级消息。

消息中以“内部数据库快照...”开头的信息仅当联机运行了 DBCC CHECKDB 且数据库未处于 SINGLE_USER 模式时才会显示。 这是因为对于联机操作 DBCC CHECKDB,内部数据库快照用于提供一组一致的数据进行检查。

本文不讨论如何排查由 DBCC CHECKDB 报告的每个特定错误,而是讨论在报告错误时的一般处理方法。 本文中的任何对 CHECKDB 的引用也适用于 DBCC CHECKTABLE 和 DBCC CHECKFILEGROUP,除非另有说明。

原因

该 DBCC CHECKDB 命令检查数据库页、行、分配页、索引关系、系统表参照完整性以及其他结构检查的物理和逻辑一致性。 如果这些检查中任何一项失败(具体取决于所选的选项),则报告错误。

这些问题的原因可能包括文件系统损坏、基础硬件系统问题、驱动程序问题、内存或存储缓存中损坏的页面,或 SQL Server 的问题。 有关如何识别已报告的错误的根本原因的信息,请参阅 调查根本原因。

分辨率

  1. 在继续还原备份或修复数据库之前,请解决系统上与硬件相关的任何问题。 应用与 I/O 路径相关的任何设备驱动程序、固件、BIOS 和操作系统更新。 请与负责整个 I/O 路径(本地计算机、设备驱动程序、存储 NIC、SAN、后端存储和缓存)及内存(RAM)的管理员合作,以隔离和解决任何问题。 示例包括更新设备驱动程序和检查整个 I/O 路径的配置。 有关如何调查根本原因的详细信息,请参阅 “调查根本原因”。

  2. 如果 DBCC CHECKDB 报告永久性一致性错误,最佳解决方案是从已知良好的备份还原数据。 有关详细信息,请参阅 还原和恢复。

  3. 应用最新的 SQL Server 累积更新或 Service Pack,以确保你未遇到任何已知问题。 检查累积更新或 Service Pack 文档,了解与数据库损坏(一致性错误)相关的任何已修复的已知问题,并应用任何相关的修补程序。 一个集中位置,可在其中搜索 SQL Server 2022、2019、2017 的详细修补程序列表中特定版本的所有修补程序。

  4. 如果 DBCC CHECKDB 错误是间歇性的,即如果在一次运行时出现,而下一次运行时又消失,则您可能遇到了磁盘缓存问题(设备驱动程序或其他 I/O 路径问题)。 请与 I/O 路径的维护人员协作,以定位和解决任何问题。 示例包括更新设备驱动程序、检查整个 I/O 路径的配置,以及更新 I/O 路径设备和系统上的固件和 BIOS。

  5. 如果无法从备份还原,CHECKDB 则具有可用于修复错误的功能。 有两个级别的修复:

    • REPAIR_REBUILD - 执行不会导致数据丢失的修复。
    • REPAIR_ALLOW_DATA_LOSS - 执行可能丢失数据的修复。

    有关详细信息,请参阅 DBCC CHECKDB 文档。

    在选择“允许数据丢失”修复时,必须谨慎,因为它可能会使数据库处于逻辑上不一致的状态。 DBCC CHECKDB 输出建议使用的最低修复级别。 多次运行CHECKDB和REPAIR_ALLOW_DATA_LOSS是一种常见的做法,直到不再报告更多错误。 这是因为当修复操作修复了一组错误时,可能会发现其他损坏的链接。 但是,如果根本原因尚未解决,可能会出现新的错误。 因此,如果在还原备份或修复之前,如果硬件或文件系统等系统级别问题导致数据损坏,必须先解决这些问题。 如果修复未能解决一致性错误,或数据库备份已损坏,Microsoft 支持工程师将无法协助物理恢复损坏的数据。

    运行 DBCC CHECKDB时,会提供建议来指示修复所有错误所需的最低修复选项。 这些消息类似于以下输出:

    CHECKDB 在数据库“mydb”中发现了 0 个分配错误和 15 个一致性错误。
    REPAIR_ALLOW_DATA_LOSS 是 ( DBCC CHECKDB mydb) 找到的错误的最低修复级别。

    修复建议是为解决来自 CHECKDB 的所有错误而应尝试的最低修复级别。 最低修复级别并不意味着此修复选项可修复所有错误。 某些错误根本无法修复。 此外,可能需要多次运行修复过程。 并非所有报告的错误都需要使用此修复级别来解决。 这意味着,并非所有由CHECKDB使用REPAIR_ALLOW_DATA_LOSS进行的修复都会导致数据丢失。 必须运行修复,以确定解决错误是否会导致数据丢失。 帮助缩小每个表的修复级别的方法之一是对任何报告错误的表使用 DBCC CHECKTABLE。 这显示了给定表的最小修复级别。

    警告

    在 CHECKDB 修复完成或数据导出或导入完成后,必须执行手动数据验证。 有关详细信息,请参阅 DBCC CHECKDB 参数。 修复后,数据在逻辑上可能不一致。 例如,修复(特别是 REPAIR_ALLOW_DATA_LOSS 选项)可能会删除包含不一致的数据的整个数据页。 在这种情况下,与另一个表具有外键关系的表可能最终包含父表中没有相应主键行的行。

  6. 尝试将数据库架构生成为脚本。 使用脚本创建新数据库,然后使用 BCP 或 SSIS 导出/导入向导 等工具将尽可能多的数据从损坏的数据库导出到新数据库。 从损坏的表导出数据可能会失败。 在这种情况下,请跳过此表,移动到下一个表,并尽可能保存能保存的内容。

  7. 检查以下文章中由 DBCC CHECKDB 生成的特定错误,并遵循提供的步骤(如果有)。 以下是一些示例:

调查数据库一致性错误的根本原因

若要确定数据库一致性错误的根本原因,请考虑以下方法:

  • 检查 Windows 系统事件日志中是否有任何与系统级别、驱动程序或磁盘相关的错误,并与硬件制造商合作解决这些问题。
  • 运行硬件制造商为计算机和/或磁盘系统提供的所有诊断程序。 大多数系统为存储(硬盘驱动器)、内存、CPU、系统板、RAID 阵列和多个其他组件提供 BIOS/UEFI 内置诊断。
  • 请与硬件供应商或设备制造商合作,确保:
  • 请考虑在报告一致性错误的数据库所在的驱动器上使用 SQLIOSim 等实用工具。 SQLIOSim 是独立于 SQL Server 引擎的工具,用于测试磁盘系统 I/O 的完整性。 SQLIOSim 附带 SQL Server,不需要单独下载。 可以在 \MSSQL\Binn 文件夹中找到它。
  • 检查累积更新或 Service Pack 文档,了解与数据库损坏(一致性错误)相关的任何已知问题,并应用任何相关的修补程序。 一个集中位置,您可以在 SQL Server 2022、2019、2017 的详细修补程序列表 中搜索特定版本的所有修补程序。
  • 检查 SQL Server 报告的任何其他错误,例如访问冲突或断言。 针对损坏的数据库的活动经常会导致访问冲突异常或断言错误。
  • 确保数据库正在使用该 PAGE_VERIFY CHECKSUM 选项。 如果报告校验和错误,则表明 SQL Server 将页写入磁盘后发生了一致性错误。 因此,应彻底检查 I/O 子系统。 有关校验和错误的详细信息,请参阅 如何在 SQL Server 中对 Msg 824 进行故障排除。
  • 在 ERRORLOG 中查找消息 832 错误。 这些错误可能表明页面在写入磁盘之前处于缓存中时可能会损坏。 有关详细信息,请参阅 如何对 SQL Server 中的 Msg 832 进行故障排除。
  • 在另一个系统上,尝试还原你知道是“干净”的数据库备份(来自 CHECKDB 的错误),然后还原跨越错误生成时间的事务日志备份。 如果可以通过还原“干净”的数据库备份和事务日志备份来“重现”此问题,请联系 Microsoft 技术支持获取帮助。
  • 数据纯度错误可能是应用程序将无效数据插入或更新到 SQL Server 表中的问题。 有关排查数据纯度错误的详细信息,请参阅 SQL Server 2005 中 DBCC 错误 2570 的故障排除。
  • 使用 chkdsk 命令检查文件系统的完整性。 在 SQL Server 运行时不要 运行 chkdsk 。 如果 SQL Server 正在写入正在检查的文件,则可能报告暂时性文件错误。 此外,/r 或 /f 之类的开关可以将文件字节移动到磁盘上的其他位置,如果 SQL Server 也在写入或读取这些文件,这种移动可能会导致损坏。 因此,在运行 chkdsk 命令之前,请务必停止 SQL Server。 此外,对/r和/f等修复选项也要谨慎。 请确保在运行修复之前备份数据库,因为如果 chkdsk 检测到磁盘错误,这些选项可能会损坏文件。

详细信息

有关 DBCC CHECKDB 的语法以及有关如何运行该命令的信息或选项的详细信息,请参阅 DBCC CHECKDB (Transact-SQL)。

如果使用 CHECKDB 时发现任何错误,则会在 ERRORLOG 中记录其他类似于以下内容的消息,以用于错误报告:

**Dump thread - spid = 0, EC = 0x00000000855F5EB0
***Stack Dump being sent toFilePath\FileName
* ******************************************************************************
*
* BEGIN STACK DUMP:
*  Date/Timespid 53
*
* DBCC database corruption
*
* Input Buffer 84 bytes -
*             dbcc checkdb(mydb)
*
* *******************************************************************************
*   -------------------------------------------------------------------------------
* Short Stack Dump
Stack Signature for the dump is 0x00000000000001E8
External dump process return code 0x20002001.

错误信息已提交到 Watson 错误报告系统。

用于错误报告的文件包括 SQLDump<nnn>.txt 文件。 此文件可用于历史目的,因为它包含从 CHECKDB 中发现的、采用 XML 格式的错误列表。

若要找出数据库上次运行 DBCC CHECKDB 且未检测到错误的时间(即上次已知无错误的 CHECKDB),请检查 SQL Server ERRORLOG。 为用户或系统数据库查找如下所示的消息。 此消息在 Windows 应用程序事件日志中使用 EventID = 17573 编写为信息级别消息:

Date/Time spid7s 数据库“master”的 CHECKDB 已于 Date/Time22:11:11.417(本地时间)完成,且没有错误。 这只是一条信息性消息;无需用户操作