DBCC在sqlserver 2000后的含义为Database Console Commands,即数据库控制台命令。其中最常用的命令有以下几个:

DBCC HELP:得到DBCC命令帮助信息

DBCC EXTENTINFO:查看指定对象分配到的区信息(非公开命令)

DBCC IND:查看指定对象分配到的数据页信息(非公开命令)

DBCC PAGE:以不同格式导出指定数据页中的数据(非公开命令)

DBCC FILEHEADER:查看数据文件文件头数据

DBCC DBINFO:查看数据库启动页中信息

 

  • DBCC HELP

提供两个功能:

  1. 使用?作参数

返回所有dbcc命令列表,若开启2588跟踪标记,则还包括非公开命令

dbcc help('?')

DBCC命令_数据

以下包含非公开命令

DBCC命令_bc_02

  1. 使用dbcc命令名称作参数

返回该命令语法信息,若开启2588跟踪标记,则还包括非公开命令(否则会报错)

DBCC命令_bc_03

查询公开命令

dbcc help('checkdb')

DBCC命令_bc_04

查询非公开命令

DBCC TRACEON(2588)

dbcc help('page')

DBCC命令_数据库_05

  • DBCC EXTENTINFO

查看指定对象分配到的区信息(非公开命令)

DBCC命令_数据_06

dbcc extentinfo [({'dbname'| dbid | 0} [, {'tablename' | tableid} [, {'indexname' | indexid | -1} [, partition_number]]])]

第一个参数:数据库名或ID。
第二个参数:表名或ID。
第三个参数:索引名或ID,如果指定为-1或省略,则显示表与其所有索引分配到的区信息
第四个参数:该参数是为兼容sql server 2000,是可选的;用于指定一个分区号。如果不给定值或者给定0, 则显示全部分区数据。
 

例子:查询hammerdb数据库中customer表与其所有索引分配到的区信息

DBCC命令_数据_07

dbcc extentinfo('hammerdb','customer')

DBCC命令_数据库_08

 

字段含义

字段名称

说    明

file_id

数据文件编号

page_id

在某个分区中的第一个页面的页面号

pg_alloc

该分区为数据库分配的页面数量m(1≤m≤8)

ext_size

分区的大小,以页面为单位

object_id

数据库对象ID

index_id

表示数据对象的类型

partition_number

分区号

rows

大约的数据行数

hobt_id

存储数据的堆或B树的存储单元ID

 

  • DBCC IND

DBCC IND 命令用于查看指定对象分配到的数据页信息,即对象的内部存储结构信息,可以通过对象名/id查到对应pageid,fileid等再通过DBCC PAGE查看对应页和文件具体信息

 

该命令有4个参数, 前3个参数必须指定。语法如下:
DBCC IND ( { 'dbname' | dbid }, { 'objname' | objid },{ nonclustered indid | 1 | 0 | -1 | -2 } [, partition_number] )
第一个参数:数据库名或ID。
第二个参数:数据库中的对象名或ID。
第三个参数:Nonclustered index ID或者1, 0, -1,-2。值的含义:

  1. Nonclustered index ID:显示索引的全部 IAM页, data页和索引页,包含LOB和 row-overflow数据页
  2. 0:只显示对象本身分配到的数据页和IAM 页信息
  3. 1:显示对象的所有页信息:包含IAM页、数据页、LOB页和row-overflow 页。如果对象含有聚集索引,则也包括索引页。
  4. -1:显示对象及其上所有索引的所有页信息:包含IAM页、数据页、其上所有索引的索引页、LOB页和row-overflow 页
  5. -2:显示对象所有的IAM页

第四个参数:该参数是为兼容sql server 2000,是可选的;用于指定一个分区号,如果不给定值或者给定0, 则显示全部分区数据。
和DBCC PAGE不同的是, SQL Server运行DBCC IND不需要开启3604跟踪标志.

我们来执行下列的命令:

DBCC IND('InternalStorageFormat','Customers',-1)

SQL Server会给我们如下的输出结果:

DBCC命令_数据_09

可以看到有2条记录,一条记录为页面类型(PageType)为10的页(IAM页)和一条记录为页面类型为1的页(数据页),它的页ID是79.

 

DBCC IND输出字段描述

Column()

Meaning(含义)

PageFID

页所在文件ID

PagePID

页ID

IAMFID

页对应的IAM页文件ID,IAM 页的IAMFID=NULL

IAMPID

页对应的IAM页ID,IAM 页的IAMPID=NULL

ObjectID

对象ID

IndexID

索引类型ID,0表示堆,1表示聚集索引,2-250表示非聚集索引。可以在sys.indexs上查找

PartitionNumber

页所属分区号

PartitionID

页所属分区内部编号

iam_chain_type

页所属IAM链类型,为in-row data或row-overflow data或 LOB data三者之一

PageType

Page type: 1 = data page, 2 = index page, 3 = LOB_MIXED_PAGE, 4 = LOB_TREE_PAGE, 10 = IAM page

IndexLevel

索引级别,0表示叶子节点,根节点的级别最高

NextPageFID

同一等级里后一个页所在文件的ID

NextPagePID

同一等级里后一个页的页ID

PrevPageFID

同一等级里前一个页所在文件的ID

PrevPagePID

同一等级里前一个页的页ID

 

  • DBCC PAGE

我们得到了数据页的页号为79,现在我们来看看79号数据页里存放的数据,这个就要用到DBCC PAGE,DBCC PAGE以不同格式导出指定数据页中的数据。语法如下:

DBCC Page ({dbid|dbname},filenum,pagenum[,printopt])

 

第一个参数:数据库名或ID。
第二个参数:文件号
第三个参数:页号

第四个参数:printopt指定输出格式:

  1. 0:默认值,输出缓冲区的标题和可读形式的页头数据
  2. 1:输出缓冲区的标题、可读形式的页头数据、每行记录的16进制数据及可读形式的偏移量表
  3. 2:输出缓冲区的标题、可读形式的页头数据、整个数据页的16进制数据及可读形式的偏移量表
  4. 3:输出缓冲区的标题、可读形式的页头数据、每行记录的16进制数据(每行后跟分别列出的它的列值)

 

设置DBCC TRACEON(3604)显示输出(否则输出会记入错误日志中)

DBCC TRACEON(3604)

DBCC PAGE(InternalStorageFormat,1,79,3)

GO

SQL Server会给我们包含4个部分的输出。

第1部分是BUFFER,里面是一些内存分配信息,对此我们没多少兴趣。

第2部分是固定96 bytes大小的页头(page header),页头会类似如下显示:

DBCC命令_bc_10

页头相关字段的含义:

  • Page @0x08F84000            同BUFFER中的bpage地址
  • m_pageId = (1:79)              文件号:页号     
  • m_headerVersion = 1         头文件版本号,一直为1          
  • m_type = 1                     页面类型,1为数据页
  • m_typeFlagBits = 0x4         数据页和索引页为4,其他页为0        
  • m_level = 0                    该页在索引页中的级数,0为叶节点
  • m_flagBits = 0x8000          数据页采用的IO错误保护类型(0x8200表示采用校验和保护方式,0x8100表示采用残缺页检测方式,0x8000为未开启)
  • m_objId (AllocUnitId.idObj) = 46    同Metadata: ObjectId             
  • m_indexId (AllocUnitId.idInd) = 256       同Metadata: IndexId
  • Metadata: AllocUnitId = 72057594040942592  存储单元的ID,sys.allocation_units.allocation_unit_id                              
  • Metadata: PartitionId = 72057594039304192   数据页所在的分区号,sys.partitions.partition_id                             
  • Metadata: IndexId = 0                                        页面的索引号,sys.objects.object_id&sys.indexes.index_id
  • Metadata: ObjectId = 277576027                      该页面所属的对象的id,sys.objects.object_id
  • m_prevPage = (0:0)                  该数据页的前一页面地址;主要用在数据页、索引页和IAM页
  • m_nextPage = (0:0)                  该数据页的后一页面地址;主要用在数据页、索引页和IAM页
  • pminlen = 221                          定长数据所占的字节数
  • m_slotCnt = 2                           页面中的数据的行数
  • m_freeCnt = 7644                    页面中剩余的空间(包括已删除记录所占空间)
  • m_freeData = 544             数据部分和偏移量列表之间的空闲空间起始位置
  • m_reservedCnt = 0           被活动事务保留的字节数,以便回滚事务
  • m_lsn = (255:8406:2)      修改该页内数据的最后一个操作产生的lsn号
  • m_xactReserved = 0       最新加入到m_reservedCnt上的字节数
  • m_xdesId = (0:0)           添加到m_reservedCnt的最近的事务id
  • m_ghostRecCnt = 0                 幻影数据的行数
  • m_tornBits = 0                         页的校验位或者被由数据库页面保护形式决定分页保护位取代

再来看下页面相关分配情况:

DBCC命令_数据库_11

  • GAM (1:2) = ALLOCATED                 在GAM页上的分配情况
  • SGAM (1:3) = ALLOCATED               在SGAM页上的分配情况
  • PFS (1:1) = 0x61 MIXED_EXT ALLOCATED  50_PCT_FULL 在PFS页上的分配情况,该页为50%满,                       
  • DIFF (1:6) = CHANGED
  • ML (1:7) = NOT MIN_LOGGED   

接下来就是用于存放实际数据的槽(slot),每条记录存放一个槽(slot)里。0号槽在页里拥有第1条数据,1号槽拥有第2条数据,以此类推。通过下面的图片,你可以看到我们记录大小是224 bytes,217 bytes(50+50+100+5+4+8) 的定长和7 bytes 的系统行开销。

DBCC命令_数据_12

页的最后一部分是行偏移数组表,我们可以用参数为1的DBCC PAGE命令来看,在输出信息的底部获得。

DBCC TRACEON(3604)

DBCC PAGE(InternalStorageFormat,1,79,1)

GO

SQL Server在输出信息的底部,给我们如下的信息:

DBCC命令_数据库_13

这个行偏移表,应该从下往上读。每条槽条目是一个2 bytes长的指针指向页里槽偏移量。这里我们插入了2条记录,所以表里有2个槽条目。第1条记录指向第96 bytes,刚好在页头后。这个行偏移表可以帮助我们管理页面的记录。在页里的行偏移表里,每条记录需要2 bytes的大小来存储。类似在堆表上建立的非聚集索引,每个非聚集索引行里都包含一个物理指针映射回堆表里的行记录。这个物理指针是[文件号:页号:槽号](file:page:solt)的结构,因此在读取页的时候,可以找到堆表里的对应行,再通过行偏移表里槽号里的偏移量,就可以在页里读取到对应的行记录。如果我们要修改页中间的记录,我们并不一定需要重组整个页,我们只要修改偏移表里偏移量即可。

DBCC命令_bc_14

在页头我们看到当前页面还有7644 bytes可以用,我们一起来验证下。

(8 * 1024) - 96 - (217 * 2)-(7 * 2)-(2 * 2)=7644 bytes

8 * 1024 = 页的总大小,8K

         96 = 页头大小 96 bytes       

 217 * 2 = 每条记录的总长 * 记录数

     7 * 2 = 每条记录的系统行开销 * 记录数

     2 * 2 = 行偏移表里每槽占用字节数 * 记录数

 

  • DBCC FILEHEADER

查看数据文件文件头数据

dbcc fileheader [( {'dbname' | dbid} [, fileid])

DBCC命令_数据库_15

完整字段如下:

RecoveryUnitId

0

FileId

1

LogicalName

Image ©sqlity.net 2014

BindingId

60371E59-22B9-412F-835C-8B88B1173F07

FileGroup

1

Size

7688

MaxSize

-1

MinSize

392

UserShrinkSize

-1

Growth

128

BackupLSN

0

RedoStartLSN

0

FirstLSN

0

MaxLSN

0

FirstUpdateLSN

0

CreateLSN

0

SectorSize

512

ActualSectorSize

512

RecoveryForkGUID

00000000-0000-0000-0000-000000000000

RecoveryForkLSN

0

DifferentialBaseLsn

285000000204700037

DifferentialBaseGuid

9C180429-584D-4F07-B5C4-9FB47480147D

Status

2

RestoreStatus

0

ReadOnlyLsn

0

ReadWriteLsn

0

MaxLsnBranchId

00000000-0000-0000-0000-000000000000

RedoTargetPointLsn

0

RedoTargetPointGuid

00000000-0000-0000-0000-000000000000

RestoreDiffBaseLsn

0

RestoreDiffBaseGuid

00000000-0000-0000-0000-000000000000

RestorePathOriginLsn

0

RestorePathOriginGuid

00000000-0000-0000-0000-000000000000

OldestRestoredLsn

0

https://sqlity.net/en/2414/dbcc-fileheader/

 

  • DBCC DBINFO

查看数据库启动页中信息

DBCC TRACEON(3604)

dbcc DBINFO [('dbname')]

DBCC命令_bc_16

 

输出如下:

 

DBINFO STRUCTURE:
DBINFO @0x0000000523D4D7F0
dbi_version = 869                   dbi_createVersion = 869             dbi_SEVersion = 0
dbi_dvSplitPoint = 0:0:0 (0x00000000:00000000:0000)                      
dbi_dbbackupLSN = 0:0:0 (0x00000000:00000000:0000)                       
dbi_LastLogBackupTime = 1900-01-01 00:00:00.000                          
dbi_nextseqnum = 1900-01-01 00:00:00.000                                 dbi_status = 0x00910000
dbi_crdate = 2018-12-12 19:37:36.263dbi_dbname = hammerdb               dbi_dbid = 6
dbi_cmptlevel = 140                 dbi_masterfixups = 0                dbi_maxDbTimestamp = 2000
dbi_dbbackupLSN = 0:0:0 (0x00000000:00000000:0000)                       dbi_RebuildLogs = 0
dbi_differentialBaseLSN = 0:0:0 (0x00000000:00000000:0000)               dbi_RestoreFlags = 0x0000
dbi_checkptLSN = 1301:23152:2 (0x00000515:00005a70:0002)                 dbi_dbccFlags = 2
dbi_COWLastLSN = 0:0:0 (0x00000000:00000000:0000)                        
dbi_DirtyPageLSN = 1301:23152:2 (0x00000515:00005a70:0002)               dbi_RecoveryFlags = 0x00000000
dbi_lastxact = 0x50a769             dbi_collation = 53284               dbi_relstat = 0x61000000
dbi_PartitionDbFlags = 0            dbi_familyGUID = ff481ae4-5b17-4d5a-a737-a7ea11b65fbb
dbi_maxLogSpaceUsed = 612675584     
dbi_recoveryForkNameStack
entry 0
hex (dec) = 0x00000000:00000000:0000 (0:0:0)                             
m_guid = ff481ae4-5b17-4d5a-a737-a7ea11b65fbb                            
entry 1
hex (dec) = 0x00000000:00000000:0000 (0:0:0)                             
m_guid = 00000000-0000-0000-0000-000000000000                            
dbi_differentialBaseGuid = 00000000-0000-0000-0000-000000000000          dbi_firstSysIndexes = 0001:00000014
dbi_oldestBackupXactLSN = 0:0:0 (0x00000000:00000000:0000)               
dbi_versionChangeLSN = 0:0:0 (0x00000000:00000000:0000)                  dbi_mdUpgStat = 0x0004
dbi_category = 0x0000000000000000   dbi_safetySequence = 0              
dbi_dbMirrorId = 00000000-0000-0000-0000-000000000000                    
dbi_pageUndoLsn = 0:0:0 (0x00000000:00000000:0000)                       dbi_pageUndoState = 0
dbi_disabledSequence = 0            dbi_dbmRedoLsn = 0:0:0 (0x00000000:00000000:0000)
dbi_dbmOldestXactLsn = 0:0:0 (0x00000000:00000000:0000)                  dbi_CloneCpuCount = 0
dbi_CloneMemorySize = 0             dbi_updSysCatalog = 1900-01-01 00:00:00.000
dbi_LogBackupChainOrigin = 0:0:0 (0x00000000:00000000:0000)              
dbi_dbccLastKnownGood = 1900-01-01 00:00:00.000                          dbi_roleSequence = 0
dbi_dbmHardenedLsn = 0:0:0 (0x00000000:00000000:0000)                    dbi_localState = 0
dbi_safety = 0                      dbi_modDate = 2018-12-12 19:37:36.263
dbi_verRDB = 234884061              dbi_delayedDurabilityOption = 0     
dbi_svcBrokerGUID = 8c856d11-5d59-47d1-90eb-b15a01d1ee5d                 dbi_svcBrokerOptions = 0x00000001
dbi_dbmLogZeroOutstanding = 0       dbi_dbmLastGoodRoleSequence = 0     dbi_dbmRedoQueue = 0
dbi_dbmRedoQueueType = 0            dbi_rmidRegistryValueDeleted = 0    dbi_dbmConnectionTimeout = 0
dbi_AuIdNext = 1099511627968        dbi_MinSkipLsn = 0:0:0 (0x00000000:00000000:0000)
dbi_commitTsOfcheckptLSN = 0        dbi_dbEmptyVersionState = 0         dbi_CurrentGeneration = 0
dbi_EncryptionHistory
 
Scan 0
hex (dec) = 0x00000000:00000000:0000 (0:0:0)                             
EncryptionScanInfo:ScanId = 0       
Scan 1
hex (dec) = 0x00000000:00000000:0000 (0:0:0)                             
EncryptionScanInfo:ScanId = 0       
Scan 2
hex (dec) = 0x00000000:00000000:0000 (0:0:0)                             
EncryptionScanInfo:ScanId = 0       
dbi_latestVersioningUpgradeLSN = 18:61:69 (0x00000012:0000003d:0045)     
dbi_PendingRestoreOutcomesId = 00000000-0000-0000-0000-000000000000      dbi_ContainmentState = 0
dbi_hkRecoveryLSN = 0:0:0 (0x00000000:00000000:0000)                     
dbi_hkLogTruncationLSN = 0:0:0 (0x00000000:00000000:0000)                dbi_hkCompatibilityMode = 0
dbi_hkRootFile = 00000000-0000-0000-0000-000000000000                    dbi_hkRootFileWatermark = 0
dbi_hkTrimLSN = 0:0:0 (0x00000000:00000000:0000)                         
dbi_hkUpgradeLSN = 0:0:0 (0x00000000:00000000:0000)                      
dbi_hkUndeployLSN = 0:0:0 (0x00000000:00000000:0000)                     dbi_heapPvsRowsetId = 0
DBCC execution completed. If DBCC printed error messages, contact your system administrator.

参考

《sqlserver 2008 数据库技术内幕》