在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
前言 有网友指出,SQL Server 2012中fn_PhysLocFormatter内部函数在解析数据行记录位置时存在错误,见:http://www.itpub.net/thread-1751655-1-1.html,实际测试后发现,一是2008R2中同样存在问题,二是不仅页号解析存在问题,槽号解析也存在同样问题。 下面先查看表NT_SiteInfo的数据行记录位置。 select SiteID,%%physloc%%,sys.fn_PhysLocFormatter(%%physloc%%) from NT_SiteInfo
下面查看表NT_SiteInfo分配的数据页情况。 dbcc ind(wjgk,nt_siteinfo,0)
Microsoft未公开的伪列%%physloc%%,类型为Binary(8),返回表中记录的RowID,格式是:前4字节表示页号,中间2字节表示文件号,最后2字节表示槽号。 对照上面的实际数据,可以发现 页号解析: 4B020000解析为576(24B),正确 3C050000解析为1340(53C),正确 99780000解析为39288(9978),错误,实际应为30873(7899) 槽号解析: 8000解析为128(0080),正确 8100解析为33024(8100),错误,应为129(0081) 下面给出错误原因。 先看下 select OBJECT_DEFINITION(object_id('sys.fn_PhysLocFormatter')) go ------------------------------------------------------------------------------- -- Name: sys.fn_PhysLocFormatter -- -- Description: -- Formats the output of %%physloc%% virtual column -- -- Notes: ------------------------------------------------------------------------------- create function sys.fn_PhysLocFormatter (@physical_locator binary (8)) returns varchar (128) as begin declare @page_id binary (4) declare @file_id binary (2) declare @slot_id binary (2) -- Page ID is the first four bytes, then 2 bytes of page ID, then 2 bytes of slot -- select @page_id = convert (binary (4), reverse (substring (@physical_locator, 1, 4))) select @file_id = convert (binary (2), reverse (substring (@physical_locator, 5, 2))) select @slot_id = convert (binary (2), reverse (substring (@physical_locator, 7, 2))) return '(' + cast (cast (@file_id as int) as varchar) + ':' + cast (cast (@page_id as int) as varchar) + ':' + cast (cast (@slot_id as int) as varchar) + ')' end 再看下reverse函数: select reverse('工人') ---- 人工 (1 行受影响) select reverse('12345工人') --------- 人工54321 (1 行受影响) select reverse('工12345人') --------- 人54321工 (1 行受影响) 结论:问题出在reverse函数上。 reverse函数的作用是字符反转,而不是字节反转,当遇到81-FE之间的字节时,被认为是双字节字符而组合在一起参与反转操作,造成了错误。 总结 以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对极客世界的支持。 |
请发表评论