SQLserver数据文件(MDF)的页面文件头结构剖析

先执行一下以下SQL语句,我的测试环境为SQL2005

dbcc traceon(3604)

go
dbcc page(master,1,0,2)

可以看到MDF文件的一些物理结构信息,其中包括重要的头96个字节。也就是第一个页面的文件头。

........

PAGE HEADER:

Page @0x03FA0000

m_pageId = (1:0)                     m_headerVersion = 1                  m_type = 15
m_typeFlagBits = 0x0                 m_level = 0                          m_flagBits = 0x8
m_objId (AllocUnitId.idObj) = 99     m_indexId (AllocUnitId.idInd) = 0    Metadata: AllocUnitId = 6488064
Metadata: PartitionId = 0            Metadata: IndexId = 0                Metadata: ObjectId = 99
m_prevPage = (0:0)                   m_nextPage = (0:0)                   pminlen = 0
m_slotCnt = 1                        m_freeCnt = 7937                     m_freeData = 3059
m_reservedCnt = 0                    m_lsn = (149:448:1)                  m_xactReserved = 0
m_xdesId = (0:0)                     m_ghostRecCnt = 0                    m_tornBits = -1073741694

........

DATA:

Memory Dump @0x62FEC000

62FEC000:   010f0000 08000000 00000000 00000000 †................         
62FEC010:   00000000 00000100 63000000 011ff30b †........c.......         
62FEC020:   00000000 01000000 95000000 c0010000 †................         
62FEC030:   01000000 00000000 00000000 820000c0 †................         
62FEC040:   00000000 00000000 00000000 00000000 †................         
62FEC050:   00000000 00000000 00000000 00000000 †................

以上蓝色的文字就是文件头的一些信息。如果这些信息损坏将会造成严重的后果。

经过简单的逐个字节分析,中间借助了windows计算器和c#的BitConverter.GetBytes函数。得出了如下文件结构图,其中每行4个字节,一共分析了文件头的前64个字节。

00:0F m_headerVersion m_type m_typeFlagBits m_level
m_flagBits m_indexId
m_prevPage(2)
m_prevPage(1) pminlen
10:1F m_nextPage(2)
m_nextPage(1) m_slotCnt
AllocUnitId.idObj
m_freeCnt m_freeData
20:2F m_pageId(2)
m_pageId(1) m_reservedCnt
m_lsn(1)
m_lsn(2)
30:3F m_lsn(3) m_xactReserved
m_xdesId(2)
m_xdesId(1) m_ghostRecCnt
m_tornBits

在数据库的头96个字节中第0x40开始直道0x5F应该都是0。

我发现只有测试页的m_pageId 的冒号前面的数字不为1时才在0x40到0x5f写入数据。但是具体代表什么还没有看出来。

姑且认为数据库第一个页面的0x00-0x3f就如上图所示,0x40-0x5f都为0(不正确的话请纠正一下)

这张图有什么用呢,如果你理解了上述参数的意义,用二进制编辑器打开一个头文件损坏的mdf文件就有可能恢复这个已经损坏的数据库。

偶不是dba也不是专业恢复数据的,只是个普通的开发人员,怎么恢复还请有经验人士补充一下。

有情提醒,这些东西非常危险,请不要随意测试,最好找一个没用的数据库来研究。

参数的意义

m_pageId
This identifies the file number the page is part of and the position within the file.  (1:143) means page 143 in file 1.
m_headerVersion
This is the page header version. Since version 7.0 this value has always been 1.
m_typea
This is the page type. The values you‘re likely to see are:
1 - data page. This holds data records in a heap or clustered index leaf-level.
2 - index page. This holds index records in the upper levels of a clustered index and all levels of non-clustered indexes.
3 - text mix page. A text page that holds small chunks of LOB values plus internal parts of text tree. These can be shared between LOB values in the same partition of an index or heap.
4 - text tree page. A text page that holds large chunks of LOB values from a single column value.
7 - sort page. A page that stores intermediate results during a sort operation.
8 - GAM page. Holds global allocation information about extents in a GAM interval (every data file is split into 4GB chunks - the number of extents that can be represented in a bitmap on a single database page). Basically whether an extent is allocated or not. GAM = Global Allocation Map. The first one is page 2 in each file. More on these in a later post.
9 - SGAM page. Holds global allocation information about extents in a GAM interval. Basically whether an extent is available for allocating mixed-pages. SGAM = Shared GAM. the first one is page 3 in each file. More on these in a later post.
10 - IAM page. Holds allocation information about which extents within a GAM interval are allocated to an index or allocation unit, in SQL Server 2000 and 2005 respectively. IAM = Index Allocation Map. More on these in a later post.
11 - PFS page. Holds allocation and free space information about pages within a PFS interval (every data file is also split into approx 64MB chunks - the number of pages that can be represented in a byte-map on a single database page. PFS = Page Free Space. The first one is page 1 in each file. More on these in a later post.
13 - boot page. Holds information about the database. There‘s only one of these in the database. It‘s page 9 in file 1.
15 - file header page. Holds information about the file. There‘s one per file and it‘s page 0 in the file.
16 - diff map page. Holds information about which extents in a GAM interval have changed since the last full or differential backup. The first one is page 6 in each file.
17 - ML map page. Holds information about which extents in a GAM interval have changed while in bulk-logged mode since the last backup. This is what allows you to switch to bulk-logged mode for bulk-loads and index rebuilds without worrying about breaking a backup chain. The first one is page 7 in each file.
m_typeFlagBits
This is mostly unused. For data and index pages it will always be 4. For all other pages it will always be 0 - except PFS pages. If a PFS page has m_typeFlagBits of 1, that means that at least one of the pages in the PFS interval mapped by the PFS page has at least one ghost record.
m_level
This is the level that the page is part of in the b-tree.
Levels are numbered from 0 at the leaf-level and increase to the single-page root level (i.e. the top of the b-tree).
In SQL Server 2000, the leaf level of a clustered index (with data pages) was level 0, and the next level up (with index pages) was also level 0. The level then increased to the root. So to determine whether a page was truly at the leaf level in SQL Server 2000, you need to look at the m_type as well as the m_level.
For all page types apart from index pages, the level is always 0.
m_flagBits
This stores a number of different flags that describe the page. For example, 0x200 means that the page has a page checksum on it (as our example page does) and 0x100 means the page has torn-page protection on it.
Some bits are no longer used in SQL Server 2005.
m_objId
m_indexId 
In SQL Server 2000, these identified the actual relational object and index IDs to which the page is allocated. In SQL Server 2005 this is no longer the case. The allocation metadata totally changed so these instead identify what‘s called the allocation unit that the page belongs to (I‘ll do another post that describes these later today).
m_prevPage
m_nextPage
These are pointers to the previous and next pages at this level of the b-tree and store 6-byte page IDs.
The pages in each level of an index are joined in a doubly-linked list according to the logical order (as defined by the index keys) of the index. The pointers do not necessarily point to the immediately adjacent physical pages in the file (because of fragmentation).
The pages on the left-hand side of a b-tree level will have the m_prevPage pointer be NULL, and those on the right-hand side will have the m_nextPage be NULL.
In a heap, or if an index only has a single page, these pointers will both be NULL for all pages.
pminlen
This is the size of the fixed-length portion of the records on the page.
m_slotCnt
This is the count of records on the page.
m_freeCnt
This is the number of bytes of free space in the page.
m_freeData
This is the offset from the start of the page to the first byte after the end of the last record on the page. It doesn‘t matter if there is free space nearer to the start of the page.
m_reservedCnt
This is the number of bytes of free space that has been reserved by active transactions that freed up space on the page. It prevents the free space from being used up and allows the transactions to roll-back correctly. There‘s a very complicated algorithm for changing this value.
m_lsn
This is the Log Sequence Number of the last log record that changed the page.
m_xactReserved
This is the amount that was last added to the m_reservedCnt field.
m_xdesId
This is the internal ID of the most recent transaction that added to the m_reservedCnt field.
m_ghostRecCnt
The is the count of ghost records on the page.
m_tornBits
This holds either the page checksum or the bits that were displaced by the torn-page protection bits - depending on what form of page protection is turnde on for the database.

时间: 2024-10-20 18:05:43

SQLserver数据文件(MDF)的页面文件头结构剖析的相关文章

读写UTF-8、Unicode文件(加上了文件头,貌似挺好用)

conf配置文件一些为UTF-8和Unicode格式,这样便可良好的支持多语言,从网上查阅资料后,将读写UTF-8.Unicode文件写了几个最精简的函数,更新后加了是否写文件头的功能,以适应更多需要,注意函数未加防错保护. 参数说明:f文件名.s写入或读取的文件内容.hs文件头.b是否读写文件头. UTF-8文件写入函数 代码 procedure SaveUTF(f:string;s:string;b:boolean=true);var  ms:TMemoryStream;  hs:Strin

SqlServer数据文件增长也很快,到底是哪些表增长造成的呢?

查询数据库中所有表的大小,哪些表的数据量较大 create table #t (name varchar(255), rows bigint, reserved varchar(20), data varchar(20), index_size varchar(20), unused varchar(20)) exec sp_MSforeachtable "insert into #t exec sp_spaceused '?'" select SUBSTRING(t.reserved

Pycharm在创建py文件时,自动添加文件头注释

操作如上图所示,一般输入的注释为:

利用文件头判断文件类型

上传文件时经常需要做文件类型判断,例如图片.文档等,普通做法是直接判断文件后缀名,而文艺青年为了防止各种攻击同时也会加上使用文件头信息判断文件类型. 原理很简单:用文件头判断,直接读取文件的前2个字节即可. 1 public class FileUtil { 2 /** 3 * byte数组转换成16进制字符串 4 * 5 * @param src 6 * @return 7 */ 8 private static String bytesToHexString(byte[] src) { 9

记一个手游app数据文件的破解

出于一些很猥琐的需要,同时自己也想做一些新鲜的尝试,周末用了大半天时间破解了某款手游的数据文件. 过程比我预想的要顺利,主要原因还是我们开发人员的懈怠,咳咳. 过程如下: 下载安装包,解压,发现几个XXX.db文件,最感兴趣的是一个50多M的XXX.db 用UltraEdit打开XXX.DB文件,没有任何线索.只发现这几个文件有相同的文件头 搜索.DB文件可能是什么文件,发现了开源库sqlite,这是一个轻量级的数据库组件,IOS就用了这个,顿时眼前一亮 下载sqlite的命令行工具,发现打不开

04 bbed修复system文件头损坏

1 启动数据库,查看trace,在mount到open, SQL> startup mount; ORACLE instance started. Total System Global Area 784998400 bytes Fixed Size 2257352 bytes Variable Size 511708728 bytes Database Buffers 264241152 bytes Redo Buffers 6791168 bytes Database mounted. SQ

Html5之基础-3 HTML概述、基础语法、文档结构

一.HTML 概述 超文本 (1) Web 是一个超文本文件的集合 (2) 超文本文件是 Web 的基本组成单元,也称为网页或 HTML 文档.Web页等,通常是以.html或.htm为后缀的文件 (3) Web页上之间通过超文本中的超级链接组织在一起 HTML 概述 (1) HTML(HyperText Markup Language):超文本标记语言,一种纯文本类型的语言 - 使用带有尖括号的"标记"将网页中的内容逐一标识出来 (2) 用来设计网页的标记语言 (3) 用该语言编写的

HTML5移动开发之路(42)——HTML4与HTML5文档结构比较

本文为 兄弟连IT教育 机构官方 HTML5培训 教程,主要介绍:HTML5移动开发之路(42)--HTML4与HTML5文档结构比较 一般来说,人们在书写包括HTML在内的文档时,习惯上按照类似于"章--节--小节"这样的层次结构来进行. 在HTML4中的描述方式: <html> <head> </head> <body> <h1>第一章 小强的HTML5移动开发之路</h1> <h2>1.1 HTM

【表空间支持的最大数据文件大小的算法】【数据库限制】【数据文件文件头保留数据块数】

本地管理表空间中设置不同大小的db_block_size时数据文件头保留空间相应例如以下:--?? db_block_size=2KB,文件头保留32个数据块,即64KB. db_block_size=4KB.文件头保留16个数据块,即64KB. db_block_size=8KB,文件头保留8个数据块,即64KB. db_block_size=16KB,文件头保留4个数据块.即64KB. db_block_size=32KB,文件头保留4个数据块.即128KB. --为什么不是64kb? 默认