关于INNODB SYSTEM RECORD infimum和supremum的学习和实验研究
接上一篇
http://blog.itpub.net/7728585/viewspace-2063921/
所用到的工具是自己写的mysqlblock和bcview,
我放到了百度云盘
http://pan.baidu.com/s/1num76RJ
供大家下载和使用
接下来就是INDEX SYSTEM RECORDS,就是infimum和supremum
如前面所介绍的,这两个系统记录是每个INNODB 块必须的,
用来标示记录的开头和结束
及infimum.next_offset--->记录1 记录1.next_offset--->记录2 记录1.next_offset--->记录n 记录n.next_offset--->supremum
我们知道在一个C语言中最后一个链表的NEXT指针指向的NULL空指针,那么这里SUPREMUM实际就是NULL空指针及0
他们位置固定在块的94-120字节,其中94-107为infimum 相关信息,而107到120为supremum相关信息
info flags 4bits
number of records owned 4bits
order 13bits
record type 3bits
next record offset 2bytes
"infimum\0" 8bytes (C语言数组以\0表示结尾)
以上是infimum固定信息
order 13bits
"supremum" 8bytes
以上是supremum固定信息
我们同样适用bcview来查看infimum信息,当然查看的还是块3(0开头实际是第4个块)
bcview km1.ibd 16 94 16|more
current block:00000003--Offset:00094--cnt bytes:13--data is:0100020041696e66696d756d00
1、info flags
这4位(4bits)标示是一个行标识,其中binary 0001表示最小的行,其中binary 0010表示是删除的行,而infimum和supremum行在我测试数据库中为binary 0000
2、number of records owned
这4位(4bits)表示在本page directory(槽)中的记录数,关于槽的概念后面详细探讨
3、order
这13位(13bits)表示记录插入到块中顺序,INFIMUM恒等于0而SPREMUM恒等于1,而数据行的ORDER从2开始
4、record type
这3位(3bits)表示记录的类型,supermum恒等于3及binary 011,infimum恒等于2及binary010,节点指针为1及001,数据行为000
5、next record offset
这2个字节 在INFIMUM中表示的是第一个行的偏移量这个偏移量是当前记录的位置+offset,这个offset直接指向了数据而相关的行头在offset-n开始n为行头的开销。
当然supermum为的偏移量就是NULL空指针了。
6、"infimum\0" OR "supremum"
这没什么好解释的就是实际的ASCII值
我们还是适用我写工具mysqlblock和bcview进行验证
[root@hadoop1 test]# mysqlblock km1.ibd -d
***************************************************
USEAGE: mysqlblock datafile -t/-d
This small tool used in study and test database,not
uesd on online database!
This tool is used to find how many blocks and types
in specified datafile,Exp:how many undo block in d
ata file!
QQ:2238980
-t Only Total blocks types in ibdata!
-d Blocks types detail in ibdata!
FILE SIZE IS : 98304
current read blocks is : 0 --This Block is file space header blocks!
current read blocks is : 1 --This Block is insert buffer bitmap blocks!
current read blocks is : 2 --This Block is inode blocks!
current read blocks is : 3 --This Block is data blocks( index pages)!
current read blocks is : 4 --This Block is new allocate blocks!
current read blocks is : 5 --This Block is new allocate blocks!
Total Block Status :
Total block : 6,Total size is: 0.093750 MB
Total undo block : 0,Total size is: 0.000000 MB
Total inode block : 1,Total size is: 0.015625 MB
Total insert buffer free blocks: 0,Total size is: 0.000000 MB
Total data(index pages) block : 1,Total size is: 0.015625 MB
Total new allocate blocks : 2,Total size is: 0.031250 MB
Total insert buf bitmap blocks : 1,Total size is: 0.015625 MB
Total system blocks : 0,Total size is: 0.000000 MB
Total transaction system blocks: 0,Total size is: 0.000000 MB
Total file space header blocks : 1,Total size is: 0.015625 MB
Total extrenl disc blocks : 0,Total size is: 0.000000 MB
Total LOB blocks : 0,Total size is: 0.000000 MB
Total Unkown blocks : 0,Total size is: 0.000000 MB
可以看到
就是实际的数据,因为我这里只有
mysql> select * from km1;
+------+---------+
| id | name |
| 2 | gaopeng |
| 4 | gaopeng |
| 5 | gaopeng |
| 6 | gaopeng |
| 7 | gaopeng |
| 8 | gaopeng |
6 rows in set (0.04 sec)
6行数据,并且是上次测试留下了,这些数据部分是从用的DELETE的空间,当然这也就是说,你的INSERT并不一定在文件中是顺序存储的,
因为delete的空间会被重用。
[root@hadoop1 test]# bcview km1.ibd 16 94 26|more
******************************************************************
This Tool Is Uesed For Find The Data In Binary format(Hexadecimal)
Usage:./bcview file blocksize offset cnt-bytes!
file: Is Your File Will To Find Data!
blocksize: Is N kb Block.Eg: 8 Is 8 Kb Blocksize(Oracle)!
Eg: 16 Is 16 Kb Blocksize(Innodb)!
offset:Is Every Block Offset Your Want Start!
cnt-bytes:Is After Offset,How Bytes Your Want Gets!
Edtor QQ:22389860!
Used gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
----Current file size is :0.093750 Mb
----Current use set blockszie is 16 Kb
current block:00000000--Offset:00094--cnt bytes:26--data is:00000000ffffffff0000ffffffff000000000000000000030000
current block:00000001--Offset:00094--cnt bytes:26--data is:0000000000000000000000000000000000000000000000000000
current block:00000002--Offset:00094--cnt bytes:26--data is:00000000ffffffff0000ffffffff000005d669d200000003ffff
current block:00000003--Offset:00094--cnt bytes:26--data is:0100020041696e66696d756d0007000b000073757072656d756d
current block:00000004--Offset:00094--cnt bytes:26--data is:0000000000000000000000000000000000000000000000000000
current block:00000005--Offset:00094--cnt bytes:26--data is:0000000000000000000000000000000000000000000000000000
我们只研究数据块current block:00000003的实际数据
分解一下:
0100020041696e66696d756d00 为infimum的相关信息
07000b000073757072656d756d 为SPREMUM的相关信息
4位
0X0 infimum
0X0 supremum
infimum和supremum行在我测试数据库中为binary 0000
0X1 infimum binary 0001 1行
0X7 supremum binary 0111 7行
由于13位不能转化为16进制直接给出二进制binary
infimum 0X0002 两字节0000 0000 0000 0010
supermum 0X000b两字节0000 0000 0000 1011
binary 0000 0000 0000 0 infimum 可以看到确实infimum在这13位上为0
binary 0000 0000 0000 1 supermum 可以看到确实supermum在这13位上为1
infimum 3位为binary 010 及10进制的2 可以看到确实infimum恒等于2及binary 010
supermum 3位为binary 011 及10进制的3 可以看到确实supermum恒等于3及binary 011
5、next record offset
infimum 2个字节为 0X0041 这里infimum指向了下一个行的指针
supermum 2个字节为 0X0000 这里supermum为空指针0X0000
那么我们就要看看infimum的指针0X0041是不是指向的数据了,
0X0041 十进制为65,这个位置是infimum header 结束位置相对偏移量及99
我们知道int类型为4BYTES而我的数据'gaopeng'为7字节
那么就是11字节
同时在我们的页数据块,当然我这里就一个块当然也就是页块了
他的数据结构实际如下:
CLUSTER KEY FIELDS 主键字节数,我这里没有就是ROWID,6字节
transaction id 固定6字节
roll pointer 固定7字节
Non-key fields 就是数据的字节数,我这里就是11字节了
那么我们可以算出起始位置为99+65=164 查看的字节数为 11+6+6+7=30
注意这里的偏移量为65很显然,这里不是物理的第一行,order 排序的第一行。order就是插入的顺序,原来的第一行被我DELETE掉了,空间重用过了。
bcview km1.ibd 16 164 30|more
current block:00000003--Offset:00164--cnt bytes:30--data is:000001cc64260000002d0272d300000d1201108000000267616f70656e67
分解一下数据
000001cc6426 ROWID
0000002d0272 transaction id
d300000d120110 roll pointer
80000002 数据2,这里8出现在第15位,可能为符号位
67616f70656e67 数据'gaopeng'的ascII值
可以看到没有问题,我们找到了他的数据,由于ROW HEADER是可变的,所以这个指针指向是数据的开头,而不包含行头
行头信息需要计算offset后像前面偏移N个字节开始,当然这内容以后再讨论
关于行的格式会在以后的文章中给出,这里重要解释infimum和supermum,
6、"infimum\0"和"supermum"
这个没什么好说的就是ASCII值
696e66696d756d00="infimum\0"
73757072656d756d="supermum"
最后
这里在做一个测试试一下 bigint UNSIGNED 类型
首先测试bigint是否为8个字节,同时测试符号位
mysql> create table km15(id bigint UNSIGNED ,name varchar(20));
Query OK, 0 rows affected (0.15 sec)
mysql> insert into km15 values(10,'gaopeng');
Query OK, 1 row affected (0.02 sec)
同样不需要主键
bcview km15.ibd 16 94 26|more
current block:00000003--Offset:00094--cnt bytes:26--data is:010002001c696e66696d756d0002000b000073757072656d756d
分解数据
010002001c696e66696d756d00 infimum
02000b000073757072656d756d supermum
infimum行的偏移量001c=28
99+28=127
Non-key fields 就是数据的字节数,我这里就是8(bigint)+7字节了=15字节
bcview km15.ibd 16 127 34|more
current block:00000003--Offset:00127--cnt bytes:34--data is:000001cc680a0000002d0e74e0000080240110000000000000000a67616f70656e67
000001cc680a
0000002d0e74
e0000080240110
000000000000000a 实际数据10
67616f70656e67 数据'goapeng'
没有问题bigint UNSIGNED为8字节同时没有了符号位当然没有符号位存储的数据最大也就是2^64 如果有符号当然少一位
就是-2^32到2^32 如果有C语言的基础也就不难理解了。
总结一下:
1、infimum和supermum 是作为数据块的行的起始和结束位置
2、infimum和supermum 固定在94-120字节,其中94-107为infimum 相关信息,而107到120为supremum相关信息
3、infimum里面offset的偏移量是一个相对偏移量,开始位置是CLUSTER KEY的开始位置,行头的偏移量需要相对偏移量-N,这个其实MYSQL中此类行便宜量的所有都是一样的
4、smalint int bigint 等 在内存存储中是有记可寻的,他类型和C语言一致。
相关普通行的格式会随后分析,其实可以看到有了infimum和supermum那么BLOCK中的数据就成了一个单项的链表。