翻译如何计算分配单元ID?

翻译如何计算分配单元ID?

原文:allocation unit IDs calculated?

原文地址:Inside the Storage Engine: How are allocation unit IDs calculated?

 

正文:

自上一篇关于纯内幕的博文已经有很长一段时间了。很多人常常问我如何从页头部存储的m_objid和m_indexId计算出分配单元ID.

当使用DBCC PAGE列出页头部的内容时,确实先需要计算,然后根据元数据(metadata)找出分配单元id(allocation unit id)、分区ID(partition id)、相关对象和索引ID。基本上,通过DBCC PAGE输出的以Metadata: 前缀的数据都没有保存在页头部(译注:即都是通过计算和查找出来的):

 计算公式如下:

  • 将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的幂:

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

GO

 

 然后你就可以使用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

 因为要用到POWER的倒数,所以下面的这个T-SQL包含有浮点数:

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来分析了。这时候,上面的这些代码可能是你的最后一根救命稻草。

posted @ 2014-10-11 15:48  misterliwei  阅读(467)  评论(0编辑  收藏  举报