帮助中心 >  技术知识库 >  数据库 >  相关技术支持 >  SQL Server数据库启动过程(用户数据库加载过程常见问题)第三部分

SQL Server数据库启动过程(用户数据库加载过程常见问题)第三部分

2016-10-07 08:22:17 7520

在经历了上面的文件级别错误后,在数据库启动的过程,还经常出现的是数据页级别的错误,相对于上面的文件错误级别,在数据页中造成的错误粒度更小,并且基本不会反映到数据库级别,也就是说在出现数据页级别的错误时候,该数据时可以正常访问的,只是在访问有错误的数据页的时候才会报错,在我们遇到这种错误的时候该如何解决呢?

下面我们依次来分析,首先我们来制作一个经典的824错误,以下部分内容牵扯到数据库部分基础,限于篇幅,我们不做详细介绍:

<1>首先我们在我们的测试库中新建一个表,我们将该表新建成一行为一个数据页的方式,也就是说一行数据库在数据库中就能承载一个数据页

复制代码

USE CnblogsTestDB
GO
CREATE TABLE [dbo].[TestPage]
(
    [a] [int] NULL,
    [b] [nvarchar](3900) NULL
) ON [PRIMARY]

复制代码

脚本很简单,一张表,两列,一列int类型,一列nvarchar(3900),一行数据的存储空间为:3900*2(nvarchar(3900))字节+4(int)+96字节(页头)+36字节(行偏移)=7932字节,我们知道一个数据页存储的信息为8K=8192字节,包括其它消耗所以该表一行数据如果填充完,一行数据将近乎占据一个数据页。

我们来添加三行数据,然后查看页信息:

复制代码

--插入三条数据
insert [TestPage]
values(1,REPLICATE('A',3900))
insert [TestPage]
values(2,REPLICATE('B',3900))
insert [TestPage]
values(3,REPLICATE('C',3900))
go--查看页信息
dbcc  traceon(3604)--查看库中页集合
dbcc extentinfo(CnblogsTestDB,[TestPage])

复制代码

可以看到,该表中现在有三个数据页,我们来看看数据页应该也是近乎沾满的

 上图显示了,通过扫描表信息,共含有3个数据页,每个数据页中的数据量存储占比到了96.55%,也就是说基本上是填充满了。

 当然,我们还可以通过DBCC PAGE命令,来查看每个页中的具体内容,我们简单的看一个页面编号为90的数据页:

通过上面的命令可以看到,该数据页中存储的为表中的第一行的数据,并且在数据库存储文件中是以十六进制方式编码存储。

当然,如果感觉此方式不直观,可以利用一个小工具进行数据页的查看,这里我推荐使?Internal Views(此工具在桦仔的博文中有详细介绍),可更直观的展示数据存储页信息:

这里我们可以点击我上面上面查看的第一行的数据内容页进行查看

 

经过上面的分析步骤,其实我的目的是想重现在SQL Server启动过程中,或者在线上的数据库经常遇到的经典错误824错误

上述过程是原理篇,因为我们必须知道数据存储的底层原理,才能理解好这个错误的原因,以及找到正确的处理方法。

 

下一步,我们来重现这个错误的原因,我们知道在我新建的测试表中含有两个字段:a和b,并且a为int类型、b为nvarchar类型

然后我们介绍了底层的存储机制,我现在将第一列a字段的整形数据内容存储改成字符串类型依次来损坏掉该数据页内容

我先将服务停掉,然后用文件编辑工具,修改此数据页内容,该数据页内容为十六进制内容,当然在我搞坏这部分数据页之前我先做一个完整备份

 

然后修改该数据页信息,这里我使用UltraEdit文本编辑工具,打开文件,找到该数据页内容

我们将上面的源数据更该一下,来把这个数据页损坏掉

 我们保存,然后重新启动该数据库看看

 这就是我们平常比较常见的824错误的过程,而此过程有可能是磁盘坏道造成,或者误修改文件等诸多原因,但是此问题还是比较常见的

当然,这种数据页面的损坏可能造成的影响不是库级别的,也就说不会造成数据库不能访问,其它表是能正常访问的,但是只是在操作此损坏的数据页的时候才会报错,但有时候这几个数据页的损坏对业务产生的影响有可能就是致命的,所以我们要解决掉。

郑重提示:上面过程也可以正确的更改数据页中的数据,但是如果没有确切的把握,基本上能把数据库搞瘫痪掉,我是为了重现问题才修改底层元数据,所以在自己的生产库中千万不要乱搞!

在数据库启动的过程中,会发生一致性校验,所以该错误应该会记录到Error的错误日志文件中,我们来看:

windows平台下的错误日志:

当然,在启动的过程中该问题有可能发生很多,比如磁盘坏道等原因,一系列的数据页可能就没法访问了。所以SQL Server会将这些损坏的页面记录到msdb系统库中,这我们在这个库中查找到损坏的页面集合:

至此,我们已经重现了经典的824错误,那我们该如何解决此问题呢? 

解决方法:

a、如果此问题出现的页面为数据承载页,也就说该页存储的为内容数据或者为聚集索引的叶子节点数据,并且存在镜像,版本在SQL Server2005以上,那么这个错误基本可以忽略,SQL Server能够自动帮你修复此错误。

b、如果此问题出现在没有镜像的环境中,那就要区分是损坏页面是否为聚集索引叶子节点数据,如果是,那就简单了,直接重建索引就好了,如果不是,那此种方案还是不能解?,判断方法如下:

利用DBCC PAGE命令查看当前数据页内容,根据ObjectId跟踪该页位于哪个对象上,Metdata:IndexID的值判断是否为索引树中的节点值,如果大于0则表示为索引值,此时,重建该索引既可以。比如:

我们根据该页的ObjectID,从数据库中查找该页所属对象。

 c、如果上述方案都不能满足,那只有采取此种方案,我们可以利用数据库备份进行还原,当然为了最大限度的避免数据库离线,我们最好采取数据页还原的方式,此种方式最为简单,还原速度也最快,能够最大限度的缩短数据库离线时间,并且保证数据完整性。

这里提示下:在SQL Server2012版本一下,SSMS不提供图像化数据页还原方式,在SQL Sever以后的版本中,有图像化界面操作。

所以,我们只能通过如下脚本进行还原:

RESTORE DATABASE CnblogsTestDB
PAGE='1:90'FROM DISK = N'F:SQLTestCnlogsTestDB.bak'WITH NORECOVERY

当然有事务日志、更新备份的,需要依次恢复这过程的所有的备份,不要忘记备份尾部日志。

但是此方法也有局限性:

如果损坏的数据页为

  1、分配页:GAM、SGAM和PFS页

  2、所有数据文件的启动页

如果发生损坏的是以上两种,则无法通过该备份恢复页方式进行恢复。如果这种情况下,建议考虑找合适的时间段进行全库的恢复操作。(推荐)

d、上述情况是在存在有备份的情况下,如果没有数据库备份,那我们只能选择最后的一招了,那就是DBCC CHECKDB命令,同样和上面一样,此种方式可能会造成数据丢失,所以不建议采用,如果能容忍数据丢失,采用的过程参照文中的上半部分。(不推荐)

 

至此,我们已经完成了一个SQL Server启动过程或者平常最经常遇到的一个经典错误824错误,我们来总结下:

824错误原因:大部分是由于磁盘存储导致的数据页损坏,导致的SQL Server在读取的时候发生了错误。

导致错误场景:磁盘坏道、突然断电等情况下经常会出现此错误。

 

----------------------------------------------------------霸气的分割线-----------------------------------------------------------------------

和824错误相关的还有一种是823错误,我们来介绍下该错误信息
由于场景所限,我就不重现该错误了,在这里我详细的介绍下这两种错误的原因和原理,就可以了,如果遇到了,解决的方式基本都是一致的,可参照上面的824错误解决方法。

SQL Server在每次写入页面的时候,会根据页面里的数据算出一个校验值?一同存储到页面中去。当下次读取页面的时候,再根据这次读到的页面数据,算出一个新的校验值。如果写入和读出的数据一模一样,那么两个校验值就是相等的。如果两个校验值不相等,就意味着上次SQL Server写入的数据和这次读取出来的一定不同,现在读取出来的数据就有问题了。

823错误就代表着SQL Server在向操作系统申请某个页面读写的时候遇到了Windows?取或写入请求失败。所以该问题的原因大部分是源自于操作系统层面,更确切的说是物理文件损坏而导致此错误,比如设备驱动程序导致等。

824错误则是在读取数据页面时候,发现数据页面有问题,比如读取出来的校验值不对等。 

当上面描述的823和824错误出现大面积的时候,或者直接部分数据文件完全坏掉的情况下,在SQL Server启动过程中就会出现数据库SUSPECT“质疑”状态。

经过我的多次数据页的破坏和摧残,我已经顺利的将我们的这个测试库给搞成?质疑状态,我们来看SUSPECT(质疑)的状态库:

这里我直接DBCC CHECKDB命令尝试着恢复下看看

 

所以到此,我们要做的就是避免上述错误的发生。如果在生产库中?生了我上面的情况,然后没有数据库备份,那么剩下来你要做的事情:我估计就是准备简历了..... 

结语

文章主要还是分析SQL Server启动过程中,加载用户数据库的时候,所遇到的一系列问题,文中部分内容需要有一定数据库基础知识才能读懂,篇幅有限,我们没有做深入的讲解分析,比如上面的几个重要的命令DBCC PAGE....DBCC CHECKDB..等等,随便一个都能写出一系列的内容,我们侧重的还是问题的解决,和问题原因分析,后续文章中会介绍这一系列的命令作用,以及正确的使用技巧。

文中部分数据库错误都是我耗费精力一步一步调整出来,目的是真实的展现错误明细,其实问题解决容易,问题重现的过程复杂。

如果经常使用SQL Server,其实这些问题都是我们会经常遇到的,所以我们要记住相应的解决方案,做的有备无患!


提交成功!非常感谢您的反馈,我们会继续努力做到更好!

这条文档是否有帮助解决问题?

非常抱歉未能帮助到您。为了给您提供更好的服务,我们很需要您进一步的反馈信息:

在文档使用中是否遇到以下问题: