当前位置:Gxlcms > 数据库问题 > SQL Server 数据库启动过程(用户数据库加载过程的疑难杂症)

SQL Server 数据库启动过程(用户数据库加载过程的疑难杂症)

时间:2021-07-01 10:21:17 帮助过:9人阅读

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:\SQLTest\CnlogsTestDB.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,其实这些问题都是我们会经常遇到的,所以我们要记住相应的解决方案,做的有备无患!

当然个人能力有限,部分不当之处,还望指出不吝赐教。

 

转:https://www.cnblogs.com/zhijianliutang/p/4100103.html

SQL Server 数据库启动过程(用户数据库加载过程的疑难杂症)

标签:文件拷贝   很多   表示   描述   --   inf   mdf   节点   img   

人气教程排行