dbcc page解析行数据
dbcc page 用法详解:
dbcc page ( {'dbname' | dbid}, filenum, pagenum [,printopt={0|1|2|3} ])
The printopt parameter has the following meanings:
· 0 - print just the page header
· 1 - page header plus per-row hex dumps anda dump of the page slot array (unless its a page that doesn't have one, likeallocation bitmaps)
· 2 - page header plus whole page hex dump
· 3 - page header plus detailed per-rowinterpretation
1、构造测试数据。
先创建一个表
[sql]
--建表
if OBJECT_ID('t1') is not null
drop table t1
go
create table t1
(
id int primary key,
v varchar(20)
)
insert into t1
select 1 ,'aa' union all
select 2 ,'bb' union all
select 3 ,'cc' union all
select 4 ,'dd' union all
select 5 ,'ee' union all
select 6 ,'ff'
开启会话X,在里面输入下面的代码:
[sql]
--执行顺序.1
begin tran
update t1
set v = 'xx'
where id = 3
--执行顺序.1
--执行顺序.3
update t1
set v = 'yy'
where id = 6
--执行顺序.3
再次开启会话Y,在里面输入代码:
[sql]
--执行顺序.2
begin tran
update t1
set v = 'mm'
where id = 6
--执行顺序.2
--执行顺序.4
update t1
set v = 'nn'
where id = 3
--执行顺序.4
然后,按照先执行会话X中的执行顺序1,然后执行会话Y中的执行顺序2,执行会话X中的执行顺序3,执行会话Y中的执行顺序4,一步一步执行。
当执行完这4个步骤后,在会话X中,显示了死锁,且会话X的事务被回滚:
同时,能在SQL Profiler中看到监控到的死锁:
从这个图中,我们可以看到详细的死锁信息,打叉的表示被回滚的会话,把鼠标放到椭圆上,会显示导致死锁的,这个会话正在运行的sql语句。
在长方形的框中,可以看到两个会话要获取X锁,左边的会话拥有下面方框中的键锁,右边的会话拥有上面的键锁,而当左边的会话想要获取上面的键锁是,被阻塞住了,而当右边的会话想要获取下面的键锁时,也被阻塞了,于是整个图像中形成了一个循环,也就导致了死锁。
2、获取更详细的阻塞信息。
通过通过sys.dm_tran_locks,可以获取到更为详细的阻塞信息。
[sql]
select resource_type,
resource_database_id, --数据库id
resource_description, --资源描述
resource_associated_entity_id, --资源关联实体id
request_mode, --请求模式
request_type, --请求类型
request_status,
request_session_id, --请求会话id
request_owner_type
from sys.dm_tran_locks
where request_session_id = 58
解析resource_associated_entity_id的值:
[sql]
--1.查询resource_associated_entity_id的意义
select *
from sys.tables
where object_id = 837578022
/*
这个id是t1表
name object_id
t1 837578022
*/
--2.查询resource_associated_entity_id的意义
select *
from sys.partitions p
where p.hobt_id = 72057594041466880
/*
这个是表t1的一个b树
partition_id object_id index_id partition_number hobt_id
72057594041466880 837578022 1 1 72057594041466880
*/
4、通过dbcc page来解析sys.dm_tran_locks中resource_description列的值:
[sql]
resource_type resource_database_id resource_description
PAGE 10 1:188
KEY 10 (b9b173bbe8d5)
KEY 10 (98ec012aa510)
为了能解析resource_description的值,需要建立一个表和一个存储过程,注意在存储过程中引用的1:188,就是上面sys.dm_tran_locks中的结果:
[sql]
--3.这里创建一个表,用来存放dbcc page的结果
if exists(select * from sys.tables where name = 'dbcc_page')
drop table dbcc_page
go
create table dbcc_page
(
ParentObject varchar(500),
Object varchar(2000),
Field varchar(1000),
Value nvarchar(max)
)
go
--创建一个存储过程
if exists(select * from sys.procedures where name = 'proc_dbcc_page')
drop procedure proc_dbcc_page
go
create procedure proc_dbcc_page
as
DBCC page(10, --数据库id : 10
1, --文件id: 1
188, --页id: 188
3) with tableresults
go
insert into dbcc_page
exec proc_dbcc_page
go
最后,我们查询一下,(b9b173bbe8d5)和(98ec012aa510),到底是哪一行数据
[sql]
--查询(b9b173bbe8d5)和(98ec012aa510),到底是哪一行数据
;with t
as
(
select OBJECT,
Field,
value,
case when charindex('Column',object) > 0
then charindex('Column',object)
else charindex('Offset',object)
end as substring_len
from dbcc_page dp
where Object like 'Slot%Column%'
or
Field = 'KeyHashValue'
),
tt
as
(
select object,
field,
value,
cast(substring(object,len('Slot')+1,substring_len-len('Slot')-1) as int) as row
from t
),
ttt
as
(
select object,
field,
value,
row, --第几行
max(case when field = 'KeyHashValue'
then value
else ''
end) over(partition by row) as KeyHashValue
from tt
)
select *
from ttt
where KeyHashValue in ('(b9b173bbe8d5)', '(98ec012aa510)')