数据库损坏(SQL Server数据库损坏、检测和简单修复 )
在一个理想的世界里,不会有数据库损坏,就像我们不会在日常生活中包括一些严重的事故一样。这种事情一旦发生,肯定会对我们的生活产生非常重大的影响,SQL Server也是如此。可能你已经好几年没有在数据库中遇到这种情况了,一旦遇到这种情况,往往会伴随着数据丢失、宕机,严重的甚至会影响到你自己的事业。因此,对于这种情况,我们需要了解数据库损坏的知识,以便提前准备,事后处理。本文将讨论数据库损坏的原因、现象、前后的一些处理 以及简单的修复 。
为什么数据库会损坏?在了解数据库损坏之前,我们应该首先了解SQL Server如何将数据保存到数据文件(MDF、NDF等)。).无论是更新数据还是插入数据,数据都应该首先驻留在内存中的缓冲池中,然后通过CheckPoint和Lazy Writer等进程将内存中的数据持久化到磁盘。在这个过程中,脏页数据从内存写入持久IO子系统。在此期间,数据可能会根据不同的IO子系统通过这些层:
Windows(写数据必须调用WINDOWS API)
Windows底层的中间层(杀毒软件、磁盘加密系统)
网卡、路由器、交换机、光学焊料、网线等。(如果输入输出子系统没有直接连接)
存储区域 控制器(如果使用存储区域 )
磁盘阵列控制器(输入输出子系统已完成磁盘阵列)
或磁盘SSD等持久存储。
因此,当数据页被写入持久存储时,它可能会经历上面列表中的几个项目。在上述过程中,硬件环境会受到很多方面的影响,如电压是否稳定、电源是否关闭、温度过高或过低、湿度等。至于软件,由于软件是人写的,可能会有bug,导致数据页面传输过程中出现错误。
此外,影响磁盘的因素还包括电压稳定性、灰尘等因素,这些因素也可能造成坏轨或磁盘整体损坏。
上述所有因素都可以归因于输入输出子系统。所以数据损坏大部分是IO子系统造成的,内存芯片也会造成数据页损坏的概率非常非常小,但是这部分情况很小,所以本文不讨论。
上述数据损坏的原因都是自然灾害和一些人为灾害。例如,当通过编辑器等手动编辑数据文件,并且数据库中存在需要重做和撤消的事务时(即没有Clean Shutdown),日志文件被删除(这通常会导致对数据库的查询)。
发现数据库损坏。在了解了数据库损坏的可能原因后,让我们看看SQL Server是如何监控数据库页面损坏的。
在SQL Server的数据库级别,可以设置页面保护类型。有三个选项:无、校验和、撕裂页面检测,如图1所示:
图1。页面保护的三个选项
关于这三个选项,首先请忽略无,在任何情况下都不要选择这个选项,这意味着SQL Server不保护页面。
其次是TORN _ PAGE _ DETECTION,在SQL Server中,数据的最小单位是页,每页是8K,但是对应的磁盘上往往有16个512字节的扇区。如果在写入持久存储的过程中,一页中只写入了一半的页面,这被称为“撕裂_页面_检测”。SQL Server从每个扇区中提取512字节的前两位作为元数据,它由16个扇区组成,32位和4字节的元数据(在页面标题中标记为m_tornBits)。通过这种元数据,可以检测是否存在部分写入的remote _ PAGE,但这种类型的页面验证无法检测页面中的写入错误。因此,在SQL Server 2005及以上版本中,尽量选择CheckSum。
在SQL Server 2005及以上版本中,引入了CheckSum,可以理解为CheckSum。当一个数据页被写入持久存储时,会根据页值计算出一个4字节的CheckSum并存储在页头(与:m_tornBits标识相同),与同一页的数据一起存储在数据库中。当数据从IO子系统读入内存时,SQL Server将根据页面中的值重新计算校验和,并将重新计算的校验和与存储在页面标题中的校验和进行比较。如果比较失败,SQL Server会认为页面已经损坏。
从CheckSum的过程中可以看出,只有在将页面写入SQL Server时才会计算CheckSum,因此如果只更改数据库选项,页面标题中的元数据不会相应更改。
与IO相关的三个错误
从上面的CheckSum原理可以看出,SQL Server可以检测到页面损坏。这时,具体表现可能是以下三种错误之一:
83错误,也就是所谓的硬IO错误,可以理解为SQL Server想要读取页面,而Windows告诉SQL Server无法读取页面。
84错误,也就是所谓的软IO错误,可以理解为SQL Server已经读取了页面,但是通过计算CheckSum等价物发现并不匹配,所以SQL Server认为页面已经损坏。
85错误,也称为重试错误。
其中,上面提到的823和824错误是错误级别为24的严重错误,因此会记录在Windows应用程序日志和SQL Server的错误日志中,导致错误的页面会记录在msdb.dbo.suspect_pages中,错误页码也会记录在SQL Server错误日志中,如图2所示。
图2.824 SQL Server错误记录中的错误描述
因此,如果我们有一个完美的备份,我们可以通过备份来恢复页面(同样,对于数据库管理员来说,有“准备”并且没有麻烦),清单1显示了一个简单的页面恢复代码。
USE [master]RESTORE DATABASE [Corrupt_DB] PAGE='1:155'FROM DISK = N'C:\xxx.bak'WITH FILE = 1, NORECOVERY, NOUNLOAD, STATS = 5清单1。一个简单的页面恢复代码,从备份中恢复文件ID1中的
还记得我们之前说过的,读取页面计算校验和时出现错误,可能是页面本身被写入持久存储,也可能是页面被读取。此时,SQL Server将尝试再次从IO子系统读取页面,这可能需要多达4次尝试。如果校验和在4次尝试中通过,则为825错误,否则为824错误。这里,应该注意的是,与823和824错误不同,825错误是等级只有10的消息。
因此,由于存在固定的错误号,您可以在SQL Server 中为823和824设置警报。
备份校验和
只有在使用页面时,才会检查上述页面校验和的正确性。备份数据库时,您可以指定CheCk选项,使备份读取的页面也计算校验和,从而确保备份的数据库不会损坏。我们可以在图3的备份选项中注意到这两项:
图3。校验和和错误后继续选项
如果启用了校验和,当在备份过程中发现页面校验和错误时,备份将终止,而如果启用了Continue_After_Error选项,当检测到校验和错误时,备份将继续,从而使备份成功。
如果为备份启用了校验和选项,除了检查每页的校验和之外,整个备份的校验和将在备份完成后计算并存储在备份头中。
此外,对于备份,我们可以通过使用CheckSum进行Restore Verifyonly来验证备份,以确保备份的数据不会损坏。
DBCC检查数据库如前所述,SQL Server有两种查找错误的 ,即读取页面时和备份时(本质上是读取页面)。但是如果我们想更积极地检查数据一致性,那么我们应该定期使用CheckDB来检查数据一致性,以免在读取生产时间数据时发现错误。
CheckDB命令将对整个数据库进行所有一致性检查。当检查对象是主数据库时,检查数据库也会检查资源数据库。
清单2显示了CheckDB的最简单用法。直接在当前数据库上下文中执行CheckDB将检查当前数据库中的所有内容。
DBCC CHECKDB清单2。2的最简单用法。检查数据库
在企业版中,CheckDB命令将使用多线程来检查整个数据库的一致性。在这个过程中,使用了内置的数据库快照,所以不会造成阻塞,但是CheckDB会消耗大量的CPU、内存和IO。因此,CheckDB应该选择是在维护窗口期间执行,还是在系统空闲时执行。
默认情况下,CheckDB命令将输出所有信息,但通常我们不关心这些信息,而只关心错误信息,因此在实践中,我们通常为DBCC指定没有显式信息的参数,如清单3所示。
DBCC CHECKDB WITH NO_INFOMSGS;清单3。CheckDB通常与No_InfoMsgs参数配对。
实际上,CheckDB是一组命令的总结,CheckDB将依次检查以下内容:
初始检查系统表
单元检查(DBCC检查)
完整的检查系统表
对所有表执行一致性逻辑检查(DBCC检查表)。
元数据检查(DBCC检查目录)
单边带检查
检查索引视图、XML索引等。
首先,当发现系统表损坏时,只能通过备份来恢复(这就是为什么备份TempDB以外的系统表非常重要)。其次,在大型数据库中,做CheckDB会花费很长时间,系统的维护窗口时间或者空闲时间可能不会覆盖这个时间,所以我们可以将CheckDB的任务分配给CHECKALLOC、DBCC CHECKTABLE和DBCC CHECKCATALOG三个命令。
有关CheckDB的更多详细信息,请参见:http://technet.microsoft.com/en-us/library/ms176064.aspx.
修复数据库损坏损坏数据库的最有效 是拥有冗余数据并使用冗余数据进行恢复。所谓冗余数据包括热备用、冷备用和热备用。
使用镜像或可用性组作为热备盘,当检测到错误时,页面可以自动修复(镜像要求高于2008,可用性组是2012的功能)。当镜像主体服务器遇到824错误时,它将向镜像服务器发送请求,将损坏的页面从镜像复制到主体服务器以解决问题。对于可用性组,如果在主副本上找到数据页,主副本将向所有辅助副本发送广播, 个响应辅助副本的页面将修复页面错误;如果错误出现在只读辅助副本上,将从主副本请求相应的页面来修复错误。这里值得注意的是,无论是哪种高可用性技术,都不会将页面错误扩散到冗余数据中,因为SQL Server中的所有高可用性技术都是基于日志的,而不是数据页面。
其次,使用热备用或冷备用来恢复页面。我已经在清单1中给出了详细的代码,所以我在这里不再赘述。
如果没有合适的备份,如果非聚集索引上存在损坏的数据页,那么您很幸运,您只需要禁用索引并重建它。
如果存在基线的完整备份,并且日志链没有中断(包括差异备份可以覆盖的日志缺失部分),则可以通过在备份结束日期后恢复数据库来修复。
最后,如果基础工作做得不好,可能需要通过丢失数据来改变数据库的一致性。我们可以通过DBCC检查数据库命令的修复允许数据丢失来修复数据库。使用此 可能会也可能不会导致数据丢失,但在大多数情况下,一致性将通过删除数据来修复。使用REPAIR_ALLOW_DATA_LOSS需要将数据库设置为单用户模式,这意味着停机。
不管修复数据库的情况如何,都要考虑是否能满足SLA。如果出现问题,发现无论如何都达不到SLA,我们只能回顾一下之前的准备工作,祈祷你不会失业。