SQL Server 如何计算分配单元 ID?

如何根据存储在每个页面标题中的 m_objId 和 m_indexId 字段计算分配单元 ID。

当 DBCC PAGE 转储页头的内容时,它会进行必要的计算和元数据查找,以便能够告诉您分配单元 ID、分区 ID、关系对象 ID 和关系索引 ID。基本上,下面的 DBCC PAGE 输出中以“元数据:”为前缀的所有内容都不会存储在页面本身上:

Page @0x00000004ED8A2000

m_pageId = (1:445) m_headerVersion = 1 m_type = 1
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0xa000
m_objId (AllocUnitId.idObj) = 97 m_indexId (AllocUnitId.idInd) = 256
Metadata: AllocUnitId = 72057594044284928
Metadata: PartitionId = 72057594039304192 Metadata: IndexId = 0
Metadata: ObjectId = 599673184 m_prevPage = (0:0) m_nextPage = (0:0)
pminlen = 8 m_slotCnt = 1 m_freeCnt = 8069
m_freeData = 121 m_reservedCnt = 0 m_lsn = (225:443:22)
m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0
m_tornBits = 0 DB Frag ID = 1

公式如下:

  • 取m_indexId并左移 48,得出值 A
  • 取m_objId并左移 16,得出值 B
  • AllocUnitId = A | B(其中 | 是逻辑 OR 运算)

使用上面的页面:

A = 256 << 48 = 72057594037927936
B = 97 << 16 = 6356992
AllocUnitId = 72057594044284928

使用 SQL Server 使用POWER函数执行此操作,因为 X 位的左移与乘以 2 的幂次 X 相同:

SELECT 256 * CONVERT (BIGINT, POWER (2.0, 48)) | 97 * CONVERT (BIGINT, POWER (2.0, 16));

然后您可以使用sys.system_internals_allocation_units和sys.partitions执行查找,如下所示:

SELECT
[a].[container_id] AS [Partition ID],
[p].[object_id] AS [Object ID],
[p].[index_id] AS [Index ID]
FROM sys.system_internals_allocation_units [a]
JOIN sys.partitions [p]
ON [p].[partition_id] = [a].[container_id]
WHERE
[a].[allocation_unit_id] = 72057594044284928;
GO

Partition ID          Object ID   Index ID
-------------------- ----------- -----------
72057594039304192     599673184    0

可以看到这些值与DBCC PAGE输出相匹配。

要将分配单元 ID 转换为在DBCC PAGE输出中看到的内容:

m_indexId = AllocUnitId >> 48
m_objId = ( AllocUnitId – ( m_indexId << 48)) >> 16

用于此的 T-SQL 涉及浮点数学,因为我们需要使用POWER的倒数:

DECLARE @alloc BIGINT = 72057594044284928;
DECLARE @index BIGINT;

SELECT @index =
CONVERT (BIGINT,
CONVERT (FLOAT, @alloc)
* (1 / POWER (2.0, 48)) -- right shift, reciprocal of left shift
);
SELECT
CONVERT (BIGINT,
CONVERT (FLOAT, @alloc - (@index * CONVERT (BIGINT, POWER (2.0, 48))))
* (1 / POWER (2.0, 16)) -- right shift, reciprocal of left shift
) AS [m_objId],
@index AS [m_indexId];
GO
m_objId               m_indexId
-------------------- --------------------
97                    256

这可以作为对DBCC CHECKDB无法处理的损坏数据库进行编程分析期间,以允许你作为最后的手段提取数据。

原文地址:https://www.cnblogs.com/VicLiu/p/15603667.html