《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逻辑一致性检查(上)
这些检查校验一个表和它的所有索引中的所有结构的一致性。在这一节,我们将一个"表"假定为"Heap或聚集索引的所有分区,所有非聚集索引的所有分区,及任何行外LOB数据"。表可能是一个常规的表、一个索引视图、一个XML索引、一个系统目录、一个空间列、一个服务代理(service broker)序列,以及内部作为一个表存储的其他任何数据库对象。
在一个单个批处理的所有表同时被检查,使用前面所描述的事实生成和事实聚集索引算法。第一个批处理包含关键的系统表,序列批处理被创建和检查直到数据库中的所有表都被检查。
每个表的一致性检查执行如下:
1、提取和检查表的所有元数据
2、对表的每个页,做以下操作:
◆ 读取和审核页
◆ 执行页级一致性检查
◆ 为页的所有记录执行记录级的一致性检查
◆ 为数据和索引记录,执行每记录的每列的列级一致性检查
3、执行交叉页一致性检查如下:
◆ 非聚集索引的交叉检查
◆ B-Tree完整检查
◆ 行偏移LOB数据一致性检查
◆ FILESTREAM一致性检查
■元数据一致性检查
DBCC CHECKED为描述每个表的大部分元数据生成一个内部缓存。这个元数据缓存广泛用于各种各样的一致性检查,DBCC CHECKED访问自个的缓存比持续地调用存储引擎的元数据子系统要快的多。元数据缓存的如下的层次体系信息:
◆ 表元数据对象 容纳描述一个表的无数据和一个索引元数据对象的链接列表
◆ 索引元数据 容纳描述一个表的每个索引的元数据,包括Heap和聚集索引。和一个行集元数据对象的链接列表
◆ 行集元数据 容纳描述每个索引的每个分区(partition)的元数据
表元数据缓存对象包括:
◆用于在DBCC CHECKED默认输出的信息的页和记录数量
◆ 表的已发现的错误数量
◆ 一个表达式求值程序(用于计算持久的和索引计算列的期望值)。只要CLR没有被在实例中被禁用,这将从查询处理器中获取。
◆状态信息,包括表是否被发现包含一个错误。
如果 CLR被禁用,表达式求值程序不能被创建,提示2518错误。如果CLR启用,但是初始化表达式求值程序出错,报2519错误。这两种情况下,计算列和UDTs不会被检查
索引元数据缓存对象包括:
◆所有与任何(用于索引的)分区函数相关的元数据,每个记录能被检查以确认它在正确的分区。
◆状态信息,包括索引是否被发现包含一个错误,对一个非聚集索引,如果一个错误被发现,非聚集索引交叉检查不会执行。
如果索引被看作在一个filegroup,而不是为DBCC CHECKFILEGROUP定义的,它不被包含在检查中,报2594错误
行集元数据缓存对象,使用最广泛的缓存对象,包含:
◆各种列和键数量
◆旨在FILESTREAM一致性检查的元数据
如果一个表或索引有一(驻留于一个脱机的或无效的文件组的)行集(即一个索引或表的一个分区Partition),表或索引不会包含在检查中。分别报2527错误和2522错误。
当一个行集元数据缓存对象被重新构建时,每个分配单元的系统目录页数量被测试以确保它们非负。SQL2005及以前的版本会发生,并报错2508:
Msg 2508, Level 16, State 3, Line 1
The In-row data RSVD page count for object "Receipts", index ID 0, partition ID
49648614572032, alloc unit ID 49648614572032 (type In-row data) is incorrect. Run DBCC
UPDATEUSAGE.
此外,一个分隔的包含每个分配单元ID的哈希表被在表中用一个链接设置到一个相关的行集元数据缓存对象。这提供了一种非常快的方式来查找描述一个特殊页的元数据。而不必在整个元数据缓存中做一个高成本的搜索。
如果一个特定的索引被请求做一致性检查,但索引不能被在数据库元数据中找到,报2591错误。
当缓存被创建时,它被检查一致性。如果任何错误发现,输出8901或8930错误。前者防止表被检查。8930会引起DBCC CHEKCED终止。例如:
■页审核
所有被DBCC CHECKDB读取的页,无论什么类型,经过进一步处理之前,都要通过审核。审核过程保证了它的页和记录是正确的,以至于更深的一致性检查算法,不会造成DBCC CHECKDB的内部问题。
DBCC CHECKDB自身不执行任何物理I / Os,相反,它使用缓冲池读取处理过程中的所有页。除了减少复杂性,这也允许DBCC CHECKDB使用缓冲池的审核。每当缓冲池读取页到内存,该页被检查以确保没有I / O错误发生,然后任何撕裂页或页面校验保护被证实。如果发现任何问题,通常是缓冲池所raise的823或824错误,但被DBCC CHECKDB抑制而转化为一个DBCC定义的错误信息,通常是错误8928和8939,如下所示:
Msg 8928, Level 16, State 1, Line 1
Object ID 1326627769, index ID 1, partition ID 72057594048872448, alloc unit ID
72057594055557120 (type LOB data): Page (1:69965) could not be processed. See other errors
for details.
Msg 8939, Level 16, State 98, Line 1
Table error: Object ID 1326627769, index ID 1, partition ID 72057594048872448, alloc unit ID
72057594055557120 (type LOB data), page (1:69965). Test (IS_OFF (BUF_IOERR, pBUF->bstat))
failed. Values are 12716041 and -4.
如果缓冲池审核失败,页不进行任何进一步的处理。否则,DBCC页审核执行。这包括以下步骤:
1、检查在页头的页ID是否正确。该检查实际上是由缓冲池读取页时执行,如果是检查失败,DBCC CHECKDB不会被通知。如果在原始系统目录检查期间审核一个关键系统目录页时失败,引发错误5256(不包含任何元数据信息),如下所示:
Msg 5256, Level 16, State 1, Line 1
Table error: alloc unit ID 334184954400421, page (1:2243) contains an incorrect page
ID in its page header. The PageId in the page header = (0:0).
如果这个检查在任何其他情况下失败,会引发8909错误,如下所示:
Msg 8909, Level 16, State 1, Line 1
Table error: Object ID 0, index ID -1, partition ID 0, alloc unit ID 844424953200640
(type Unknown), page ID (1:26483) contains an incorrect page ID in its page header.
The PageId in the page header = (0:0).
2、检查页面的类型是否为有效分配单元的一部分。例如,一个数据页应不应该被设置为一非聚集索引的分配单元。如果此检查失败,引发8938错误,如下所示:
Msg 8938, Level 16, State 1, Line 1|
Table error: Page (1:4667), Object ID 1877736499, index ID 1, partition ID
72044394032172426, alloc unit ID 72044394045227020 (type LOB data). Unexpected page
type 1.
3、检查每一页的记录是否具有正确的结构和不具有诸如任何错误指针(如,指向不同的记录或指向空闲空间)。 如果任何记录结构的审核检查失败,错误8940至8944的任何一个会被引发,如下所示:
Msg 8941, Level 16, State 1, Line 1
Table error: Object ID 0, index ID -1, partition ID 0, alloc unit ID 72057613244301312
(type Unknown), page (3:45522). Test (sorted [i].offset >= PAGEHEADSIZE) failed. Slot
114, offset 0x12 is invalid.
Msg 8942, Level 16, State 1, Line 1
Table error: Object ID 0, index ID -1, partition ID 0, alloc unit ID 72057613244301312
(type Unknown), page (3:45522). Test (sorted[i].offset >= max) failed. Slot 0, offset
0x72 overlaps with the prior row.
Msg 8944, Level 16, State 12, Line 1
Table error: Object ID 0, index ID -1, partition ID 0, alloc unit ID 72057613244301312
(type Unknown), page (3:45523), row 0. Test (ColumnOffsets <= (nextRec - pRec))
failed. Values are 25 and 17.
作为页审核过程的一部分,任何页上的页压缩信息被验证,包括每个页压缩信息(CI)记录(持有在一个锚内嵌的CI记录前缀和压缩字典(偏移加上值的数组)。在此记录任何破损引发5274错误:
一旦页面通过审核过程,页头部的分配单元ID被用于查询元数据哈希表,以找到在页记录中什么被存储的所有元数据。该页被检查,以确定它是否已自上次完全备份进行改变。如果有变,有关的差异位图并没有被正确设置以指示该变化,报2515错误,如下所示:
Msg 2515, Level 16, State 1, Line 1
The page (1:24), object ID 60, index ID 1, partition ID 281474980642816, allocation unit ID
281474980642816 (type In-row data) has been modified, but is not marked as modified in the
differential backup bitmap.
一旦这些通用的检查全部完成,根据其类型该页面被进一步处理。
■数据和索引页处理
数据页和索引页处理使用相同的高级别算法,并为每个记录操作如下:
◆对于有行外LOB数据的记录,在内存中完全实例化记录(引入任何行溢出列)。对于没有行外LOB数据的简单记录,该记录被直接从包含它的页处理。
◆检查记录长度是否正确,同时考虑将任何版本信息附加到该记录的末尾。
◆如果记录包含数据(即,不是一个克隆的记录),遍历记录中的所有列,并处理它们。
◆检查记录中是否无反物质(antimatter)列,如果这个检查失败,显示一个失败的联机索引操作, 5228或5229错误输出,如下所示:
Msg 5228, Level 16, State 3, Line 1
Table error: object ID 2073058421, index ID 0, partition ID 72057594038321152, alloc
unit ID 72057594042318848 (type "In-row data"), page (3:23345), row 12. DBCC detected
incomplete cleanup from an online index build operation. (The anti-matter column value
is 14.)
◆检查每个记录的版本信息,如果它存在,如果一个记录有版本信息附加到它,但页头部不显示页面上有记录的版本,此时输出错误5260。如果一个记录有一个NULL版本的时间戳,但却有一个非Null的版本链指针信息,错误5262输出。
注意:版本存储自身的有效性不会被DBCC CHECKED检查。
◆生成来自记录和它的内容(例如,B-tree树链接事实和LOB链接事实)的所有必要事实。
对于未存储在Heap数据页的记录,记录必须按已定义的聚集或非聚集索引键排序。当 一致性检查在整个页进行时,之前记录的被记住,以使他们能够与当前正在处理的记录进行比较。如果记录不正确排列,错误2511输出,如下所示:
Msg 2511, Level 16, State 1, Line 1
Table error: Object ID 142675606, index ID 1, partition ID 72057594295025664, alloc unit ID
72057594301906944 (type In-row data). Keys out of order on page (1:1124457), slots 59 and 60.
对于未存储在Heap数据页的记录,页上的记录必须也有惟一的键值,这也应用到索引,注意仅仅在相关度上,即使索引被定义为non-unique。在存储引擎级别,每一记录必须被惟一标识。如果两条记录有相同键值,错误2512输出,如下所示:
Msg 2512, Level 16, State 2, Line 1
Table error: Object ID 4, index ID 1, partition ID 262144, alloc unit ID 262144 (type In-row
data). Duplicate keys on page (1:4224) slot 9 and page (1:4224) slot 10.
一旦所有记录被处理,页头部的下列记数被检查:
1、页上的记录数(slot数)
2、页上的克隆记录数
如果记录数不正确,报8919错误。如果克隆记录数不正确,报8927错误:
Msg 8927, Level 16, State 1, Line 1
Object ID 29, index ID 1, partition ID 281474978611200, alloc unit ID 281474978611200 (type
In-row data): The ghosted record count in the header (0) does not match the number of
ghosted records (1) found on page (1:309).
对于Heap中的数据页,自由空间数被检查(对应与相关的PFS页的相应字节)。如果两个不匹配,报8914错误:
Msg 8914, Level 16, State 1, Line 3
Incorrect PFS free space information for page (1:2511951) in object ID 357576312, index
ID 0, partition ID 72057594040156160, alloc unit ID 72057594044284928 (type In-row data).
Expected value 100_PCT_FULL, actual value 95_PCT_FULL.
中篇关注:列处理、文本页处理