《Microsoft Sql server 2008 Internals》读书笔记订阅地址:
http://www.cnblogs.com/downmoon/category/230397.html/rss
《Microsoft Sql server 2008 Internals》索引目录:
《Microsoft Sql server 2008 Internal》读书笔记--目录索引
上篇关注元数据一致性检查、页审核、数据和索引页处理;本文我们继续了解per-table逻辑一致性检查,将继续关注:列处理、文本页处理。
■Per-Table逻辑一致性检查(中)
■列处理
对于数据和索引记录,每一列按类别处理。在这一部分描述的检查中的许多(检查),会引发2537(“坏的记录”)错误信息并附带了一些特定的文本信息以便于准确标记问题。
对于复杂的列(即,存储LOB或FILESTREAM数据或链接),列结构被检查同时被提炼出相关的链接事实。如果一复杂列被发现破损,错误8960输出。
1、计算列
如前所述,一个表达式计算器被为每个对象编译,包含计算列或CLR的UDT。如果表达式计算器不能编译,这些列不能被一致性检查。
该表达式计算器被调用以计算持久计算列,或者存在于索引记录中的计算列。它返回一个值,然后与数据或索引记录的持久值比较。如果两个值的Null状态不同,或两个值的字节比较不同,则返回错误2537。
对于UDT列,会进行表达式计算器比较。它通过完整的记录被检查并返回True或False值,取决于UDT的比较。
应该指出的是,表达式计算器对象不是线程安全的。这意味着,当DBCC CHECKDB正在并行运行跨多个处理器内核(每一个处理器内核一个线程)时,只有一个处理器内核可以访问,并在某个时间段内使用表达式计算器。多处理器内核能够处理来自同一个表中的计算列的页,因此,所有的内核需要访问表达式计算器。当然,内部同步,可以防止这一点,但不可避免地,一个或更多的处理器内核可能要等待访问。如同任何相互排斥机制的案例,这可能影响到大量计算列或CLR架构中的UDT的重负载系统的性能。
2、NULL和长度检查
三个检查执行如下:
◆可变长度的列是NULL时不能有非零数据长度。如果此检查失败,报告错误7961。
◆一个被作为NOT NULL创建的列不能有一个null值。如果此检查失败,报告错误8970。
◆一个列不能长度大于它的无数据定义的最大行内长度。如果此检查失败,报告错误2537。
3、数据纯度检查
数据纯度检查,检查列值是否在列的数据类型定义的范围内。一个例子是一个破损的SMALLDATETIME列值(分钟值超过1440或更多)已进入第二天,
在SQL Server2000及以前的版本中,超出边界的值可能会被导入,但在SQL Server2005及以后版本中,这不会再发生了。这是因为SQL Server2005开始推出新的“pure”--纯化功能。
纯的数据库默认有数据纯度检查,并不能被禁用。
不纯的数据库默认不运行数据纯度检查。必须使用With Data_Purity选项请求。一个数据库如果是由SQL Server 2005之前的版本创建的不纯的数据库,升级到SQL Server2008后,并没有运行数据纯度检查。一旦数据纯度检查已运行没有错误,数据库正在不可逆转地切换到纯数据库。数据库的纯度状态存储在引导页。
下图是SQL Server数据类型和为它们而执行的数据纯度验证:
注意:压缩值(无论是通过行压缩,页压缩,VARDECIMAL)必须在未压缩前被检查。如果一个大表、文件组或数据库被压缩,可能添加额外的CPU开销来运行DBCC CHECKDB。
如果数据纯度检查的任何列值失败,返回2570错误信息,如下:
Msg 2570, Level 16, State 3, Line 1
Page (1:152), slot 0 in object ID 2073058421, index ID 0, partition ID 72057594038321152,
alloc unit ID 72057594042318848 (type "In-row data"). Column "c1" value is out of range for
data type "datetime". Update column to a legal value.
这些错误无法修复,必须用手工处理。做法见知识库文章923247(http://support.microsoft.com/kb/923247)。
4、分区(partition)检查
如前所述,如果被检查的表或索引被分区,索引元数据缓存对象包含所有关于用到的分区函数的信息。
一旦所有列值的检查完成,每个页上的记录被测试,以确保它在正确的分区。对分区使用的列被通过内部查询处理器从每个记录提取到一个Helper函数。Helper函数计算分区函数的,,并返回分区ID(该记录的一部分)。如果返回的分区ID不匹配(该页的一部分)分区ID,错误8984和8988输出,如下所示:
Msg 8984, Level 16, State 1, Line 1
Table error: Object ID 2073058421, index ID 0, partition ID 72057594038452224. A row should
be on partition number 2 but was found in partition number 3. Possible extra or invalid keys
for:
Msg 8988, Level 16, State 1, Line 1
Row (1:162:0) identified by (HEAP RID = (1:162:0)).
8984错误标识包含错误的分区,8988错误标识不正确分区记录的物理位置,还有可用于访问记录(或堆的物理RID分区)的索引键。
5、稀疏列检查
定义一个列为稀疏列(Sparse)是SQL Server2008的新功能,稀疏列是NULL,根本不存储在记录中,甚至不在Null的位图中。这意味着,NULL值,在记录中真正零空间占用。当稀疏列非null时,它存储在一个特殊的稀疏列数组,而又被存储为一个记录的可变长度列数组变量的可变长度列。稀疏列数组一致性检查被查询处理器执行,出错报为正常列损坏。
■文本页处理
文本页用于存储LOB的值(或者说实际的LOB行外存储值或非LOB的可变长度列已被从行外数据引入为行溢出数据)。在所有的调用文本记录或LOB链接的错误消息中,分配单元类型可以是LOB数据或行溢出数据。
有多种类型的文本记录,用于以各种方式构建松散的存储LOB值的文本树。该文本记录存储在两种文本页类型,显示专用于单个LOB值或多个LOB值之间被共享。这两种类型的文本页被使用相同的算法处理,如下:
◆实例化记录,并检查它是一个有效的文本记录。
◆检查每个记录的版本信息,如果它存在。如果一个记录有版本信息附加到它,但在页面头部不显示页已经记录版本,错误5260输出。如果一个记录有一个NULL版本的时间戳,但却有个非Null的版本链指针,错误5262输出。
◆从记录和它的内容生成所有的必要的事实(即LOB链接事实)
当检查一个文字记录是否有效时,多种类型的带有与各种结构的文字记录必须是其中的一部分。除了常规的记录格式结构检查,定义的文本检查文执行如下:
◆删除的有版本信息的文字记录,必须有正确的行大小。如果检查失败,错误2537报出。
◆该文本记录必须至少容纳文本的叶级节点的最小尺寸。如果此检查失败,错误2537报出。
◆文本记录必须在正确的文本页类型。如果此检查失败,错误8963报出:
Msg 8963, Level 16, State 1, Line 1
Table error: Object ID 1326627769, index ID 1, partition ID 72057594048872448, alloc
unit ID 72057594022622331 (type LOB data). The off-row data node at page (3:23345),
slot 12, text ID 89622642688 has type 3. It cannot be placed on a page of type 4.
◆非叶级文本记录必须不能比可能存储在它们的文本记录类型(或它们的子链接数组,或最大许可的文本树 fan-out)拥有更多的子节点, 如果这些检查失败,错误2537报出。
◆文本记录必须有一个有效的类型。如果检查失败,报8962错误。
文本记录的错误通常伴随8929错误,该错误提示链接到破损的文本记录的数据或索引记录。
Msg 8929, Level 16, State 1, Line 1
Object ID 1326627769, index ID 1, partition ID 72057594048872448, alloc unit ID
72057594055622656 (type In-row data): Errors found in off-row data with ID 89622642688 owned
by data record identified by RID = (1:77754:1)
一旦所有的记录已被处理,在页头部的各种计数器被检查:
1、页上的记录数(slot数)
2、页上的克隆记录数
如果记录数不正确,报8919错误。如果克隆记录数不正确,报8927错误:
自由空间数被检查(对应与相关的PFS页的相应字节)。如果两个不匹配,报8914错误:
Msg 8914, Level 16, State 1, Line 1
Incorrect PFS free space information for page (1:35244) in object ID 1683128146, index ID 1,
partition ID 223091033422352, alloc unit ID 81405523118118176 (type LOB data). Exected value
0_PCT_FULL, actual value 100_PCT_FULL
下篇将关注交叉页一致性检查(Cross-page Consistency checks)