ala*_*ncc 2 sql-server database-internals
我正在阅读关于如何根据 m_indexId 计算分配单元 ID的文章http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-how-are-allocation-unit-ids-calculated/和 m_objID。然后我通过执行以下命令在我的数据库之一上尝试:
DBCC TRACEON(3604);
DBCC PAGE (UFDATA_008_2013, 1, 73057, 3);
GO
Run Code Online (Sandbox Code Playgroud)
输出结果是:
PAGE HEADER:
Page @0x10008000
m_pageId = (1:73057) m_headerVersion = 1 m_type = 1
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x8000
m_objId (AllocUnitId.idObj) = 1913890731 m_indexId (AllocUnitId.idInd) = 0
Metadata: AllocUnitId = 406903719657472 Metadata: PartitionId = 406903719657472
Metadata: IndexId = 1 Metadata: ObjectId = 1913890731 m_prevPage = (1:92774)
m_nextPage = (0:0) pminlen = 11 m_slotCnt = 61
m_freeCnt = 3241 m_freeData = 4829 m_reservedCnt = 0
m_lsn = (4028:6215:30) m_xactReserved = 0 m_xdesId = (0:0)
m_ghostRecCnt = 0 m_tornBits = 0
Run Code Online (Sandbox Code Playgroud)
然后我用上面文章中的公式计算分配单元ID为(0 << 48) + (1913890731 << 16) = 125428742946816,不等于输出Metadata:AllocUnitId(406903719657472)。为什么?
我可以确认页面已分配,因为我使用以下命令列出分配给表“AADomDataColSet”的所有页面:
DBCC TRACEON(3604);
Dbcc ind(UFDATA_008_2013, ‘AADomDataColSet’, -1);
Run Code Online (Sandbox Code Playgroud)
结果如下:
您可以找到分配给此对象的页面 (1, 73057)。
谢谢
这似乎与 Paul 帖子的评论中讨论的案例相同。他指出原因是页面不再分配(注意元数据IndexId = 1,但m_indexid = 0)。
使用 Paul 的脚本解码分配单元 ID:
DECLARE @alloc BIGINT = 406903719657472;
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];
Run Code Online (Sandbox Code Playgroud)
结果:
这与DBCC PAGE
输出中的 m_objid 匹配。
如果使用索引 ID 1,计算是正确的,再次使用保罗帖子中的公式:
SELECT allocation_id =
1 * CONVERT (BIGINT, POWER (2.0, 48)) | -- index id
1913890731 * CONVERT (BIGINT, POWER (2.0, 16)); -- object id
Run Code Online (Sandbox Code Playgroud)
因此,您的实际问题似乎根本与分配单位计算无关;相反,您是在问为什么DBCC PAGE
显示 m_indexId (AllocUnitId.idInd) = 0
页面已分配并与索引 1 相关联 - 如DBCC IND
输出所示。
那个,我不知道。我所知道的是,计算对我来说是双向的,在 SQL Server 2012 build 6518 上进行测试。也许你的 SQL Server 版本或表有一些问题,这意味着AllocUnitId.idInd
没有正确报告。如果没有具体的、可重复的细节,您可能需要问问保罗本人(尽管他目前正在度假)。
这可能是一些边缘情况。例如,这篇文章说m_indexId
如果数据库是从 SQL Server 2000 升级的,可能会有所不同。尝试重建表,这通常可以解决这些问题。