前言
有网友指出,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
SiteID
%%physloc%%
sys.fn_PhysLocFormatter(%%physloc%%)
1
0xE900000001000000
(1:59648:0)
23
0xE900000001000100
(1:59648:1)
24
0xE900000001000200
(1:59648:2)
......
149
0xE900000001007F00
(1:59648:127)
150
0xE900000001008000
(1:59648:128)
151
0xE900000001008100
(1:59648:33024)
152
0xE900000001008200
(1:59648:33280)
......
226
0xE90000000100CC00
(1:59648:52224)
227
0xE90000000100CD00
(1:59648:52480)
228
0x4B02000001000000
(1:587:0)
229
0x4B02000001000100
(1:587:1)
......
360
0x4B02000001007F00
(1:587:127)
361
0x4B02000001008000
(1:587:128)
362
0x4B02000001008100
(1:587:33024)
363
0x4B02000001008200
(1:587:33280)
......
422
0x4B0200000100BD00
(1:587:48384)
423
0x4B0200000100BE00
(1:587:48640)
424
0x3C05000001000000
(1:1340:0)
425
0x3C05000001000100
(1:1340:1)
......
552
0x3C05000001008000
(1:1340:128)
553
0x3C05000001008100
(1:1340:33024)
596
0x3C0500000100AC00
(1:1340:44032)
597
0x9978000001000000
(1:39288:0)
......
658
0x9978000001003D00
(1:39288:61)
下面查看表NT_SiteInfo分配的数据页情况。
dbcc ind(wjgk,nt_siteinfo,0)
PagePID
IAMFID
IAMPID
PageType
IndexLevel
NextPagePID
PrevPagePID
238
NULL
NULL
10
NULL
0
0
233
1
238
1
0
587
0
587
1
238
1
0
1340
233
1340
1
238
1
0
30873
587
30873
1
238
1
0
0
1340
Microsoft未公开的伪列%%physloc%%,类型为Binary(8),返回表中记录的RowID,格式是:前4字节表示页号,中间2字节表示文件号,最后2字节表示槽号。
对照上面的实际数据,可以发现sys.fn_PhysLocFormatter
在解析记录位置时,既有采用高字节在前的BIG_ENDIAN格式,又有采用低字节在前的LITTLE_ENDIAN格式,造成采用高字节在前的BIG_ENDIAN格式解析的数据错误:
页号解析:
E9000000解析为59648(E900),错误,实际应为233(E9)
4B020000解析为576(24B),正确
3C050000解析为1340(53C),正确
99780000解析为39288(9978),错误,实际应为30873(7899)
槽号解析:
8000解析为128(0080),正确
8100解析为33024(8100),错误,应为129(0081)
下面给出错误原因。
先看下sys.fn_PhysLocFormatter
函数的定义:
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之间的字节时,被认为是双字节字符而组合在一起参与反转操作,造成了错误。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]