• 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无法处理的损坏数据库进行编程分析期间,以允许你作为最后的手段提取数据。

  • 相关阅读:
    ORACLE查询删除重复记录三种方法
    是否可以从一个static方法内部发出对非static方法的调用
    协程(微线程)
    多线程、多进程
    python3.6.5修改print的颜色
    Python之时间和日期模块
    Python之字符(2)
    Python之字符
    python之列表
    Python中的文件操作
  • 原文地址:https://www.cnblogs.com/VicLiu/p/15603667.html
Copyright © 2020-2023  润新知