GAM 间隔的步长是多少

Mic*_*een 7 sql-server storage-engine database-internals

出于兴趣,我正在阅读有关Microsoft SQL Server 文件的内部 结构的内容。IAM 页面的连接方式相当明显。然而,我不清楚在哪里可以找到后来的 GAM 页面。

据记载,每个文件中的第一个GAM页是第2页。DBCC PAGE 证实了这一点。上面的链接指出在“4GB”或“64,000 个范围”之后还有另一个 GAM 页面。当我查看这些地方时(它们不是相同的数字),我没有找到 GAM 页面。

在 SQL Server 数据文件中,距离第一个 GAM 页多少页才能找到第二个 GAM 页(GAM 间隔的“跨度”)?

Mic*_*een 9

我有一个 TB 大小的数据库。应该有很多 GAM 页面可供查找。

让我们首先检查一下这些文档的进展。4GB 是 524,288 个页面。将此偏移量添加到第 1 页的 2 并使用 DBCC PAGE,不会返回 GAM 页。搜索任意一侧的几个范围也不会返回 GAM 页面。

64,000 个盘区相当于 512,000 个页面。查看页面 512,002 及其邻居也不会返回 GAM 页面。看起来这些都是粗略的近似值,而不是有关文件结构的硬事实。

让我们再次检查第一个 GAM 页面的标题。

dbcc traceon(3604);
dbcc page('Sandbox', 1, 2, 0);
Run Code Online (Sandbox Code Playgroud)

m_prevPage 和 m_nextPage 均为零。没有可遵循的页面链。

不过,m_slotCnt 是 2。我想知道不同的记录代表什么?使用dbcc page('Sandbox', 1, 2, 1);显示第一个记录的长度为 94,第二个记录的长度为 7,992。由于每个 GAM 位代表一个范围,7992 字节代表 511,488 个页面。遗憾的是,该偏移量中也没有 GAM 页面。稍后会详细介绍这一点。

现在,该博客建议分配位图可能没有槽数组。因此,当我询问每行信息时,DBCC 可能会感到困惑,而这两个“记录”实际上是一个连续的位图。计算总和后得出 517,504 页,但不幸的是,没有第二个 GAM 页。

再次查看第 2 页,但这次是详细的每行解释(选项 3),我明白了

(1:0)        - (1:369568)   =     ALLOCATED
(1:369576)   -              = NOT ALLOCATED
(1:369584    - (1:511224)   =     ALLOCATED
Run Code Online (Sandbox Code Playgroud)

我在这里找到了一个描述(在第 3.GAM 节下),其中写着“[511224] 是此范围内最后一个范围的第一页。” 因此,下一个范围的第一页将是 511232。由于这将是新 GAM 范围的开始,我希望在附近找到另一个 GAM 页面。它位于第 511232 页。

重复此操作,我在 1022464、1533696 和 2044928 处找到了更多 GAM 页面。这些页面之间有一致的间隔 511232。我得出结论,这是 GAM 间隔的步幅。为了进行检查,我取了任意倍数 511232 * 127 = 64926464,果然,它也是一个 GAM 页。

向后计算 511232 个页面是 63,904 个范围,在 GAM 页面映射中相当于 7,988 个字节。这比我在槽 2 中找到的记录 7,992 少了 4 个。这恰好是记录头的长度。我早该意识到的。


Eri*_*ing 9

来源

\n

很长一段时间以来,这已经在很多地方记录下来。我第一次看到它是在 2012 年的这篇博客文章中:

\n\n
\n
    \n
  • GAM:页面 ID = 2 或页面 ID % 511232
  • \n
  • SGAM:页面 ID = 3 或 (页面 ID \xe2\x80\x931) % 511232
  • \n
  • PFS:页面 ID = 1 或页面 ID % 8088
  • \n
\n
\n

这些页面的标识也已通过以下代码块包含在sp_WhoIsActive中:

\n
CASE\n    WHEN x.page_no = 1 OR x.page_no % 8088 = 0 THEN \'PFS\'\n    WHEN x.page_no = 2 OR x.page_no % 511232 = 0 THEN \'GAM\'\n    WHEN x.page_no = 3 OR (x.page_no - 1) % 511232 = 0 THEN \'SGAM\'\n    WHEN x.page_no = 6 OR (x.page_no - 6) % 511232 = 0 THEN \'DCM\'\n    WHEN x.page_no = 7 OR (x.page_no - 7) % 511232 = 0 THEN \'BCM\'\n    WHEN x.page_no IS NOT NULL THEN \'*\'\n    ELSE NULL\nEND AS page_type\n
Run Code Online (Sandbox Code Playgroud)\n

这对于阅读本文并希望识别其他重要页面类型的人来说可能很有用。

\n