DB2是怎么样在表空间中找到所需要的数据的?它的实现原理就是表空间映射机制,这个概念说白了就是数据在表空间内部的存储方法。DB2有一套有效组织数据的算法,实现了一个最朴素的需求,即数据能存储起来,想用的时候能找的到,要是只会存,关键时候想用找不到,岂不糟糕?拿表来说,表是DB2进行数据存储的数据库对象(索引一样也可以看成是存着数据的表),DB2在向表中写数据时,一次写一个extent,所以一个extent必定只属于某个表,extent是表空间的空间使用分配单位。
用来管理extent是如何分配的,叫做空间映射页,简称SMP。别被字面迷惑,SMP虽说叫做空间映射页,简称也是带P字,但它其实是一个extent,SMP也需要存储起来啊,凡是需要存储的,就要占用最少一个extent,所以SMP其实是一个特殊的extent,这个特殊并不是SMP这个extent在长相上有什么特殊,而是特殊在它存储的数据特殊,这个extent是用来记录其他extent分配的。
表空间的第2个extent(即extent 1,extent
0是表空间的头)就是表空间的第1个SMP。一个extent能容纳的记录容量有限,所以在表空间中,可能存在多个SMP。DB2让每个保存着SMP数据的extent,都记录下一个保存着SMP数据extent的位置映射,这样表空间中所有的SMP就被串起来了,DB2轻易就能知道在这个表空间中所有extent的分配情况。
OK,有了SMP等于DB2把一个表空间的extent都做了标识,不会把已经分配的extent再分配。但仅仅是这样还不够,表空间里存的是数据库对象,还是拿表来举例,表需要知道哪些extent是存储自己数据的,不能越界读人家的数据呀,这就要靠EMP来实现,EMP是extent映射页的意思,每个数据库对象都有自己EMP,记录属于存储自己数据的extent的分布,这样才不会串台,EMP保证了对象自己用自己的extent。
表空间的第3个extent,也就是extent
2,在这个extent里存了一个表空间自己使用的内部表,这个表你可以理解为像下面这样的一个表:
对象名字
这个对象EMP所在位置
TABLE1
extent 100
TABLE2
extent 27
INDEX1
extent 231
如果要访问TABLE1,那么需要先找到它的EMP,就能知道TABLE1所有占用的extent在哪了,读extent
2通过这个表知道,TABLE1的EMP藏在extent 100里,于是到extent 100里读,extent
100的样子就像下面这样:
EXTENT 99
Page X
某某数据
EXTENT 100
Page X+1
…
(包含extentsize个Page)
extent 121,extent122,extent156
EXTENT 101
Page X+extentsize
某某数据
好了,这个表的数据就在extent
121、extent122、extent156里。
说了这么一堆,现在我们用db2dart来感受一下,看看DMS表空间中的地址映射究竟是什么样。
先找一个DMS表空间:
db2inst1@psuse:~> db2
"select tbsp_id,tbsp_name from sysibmadm.snaptbsp where
tbsp_id>3 and tbsp_type='DMS'"
TBSP_ID TBSP_NAME
----------- -----------------------
5
TS1
1 record(s) selected.
db2inst1@psuse:~> db2
"select tableid,tabname from syscat.tables where tbspaceid=5 fetch
first 1 rows only"
TABLEID
TABNAME
---------- ------------------------------
4 T2
1 record(s) selected.
--就拿这个T2表开刀!
db2inst1@psuse:~> db2
connect reset
DB20000I The SQL command completed successfully.
db2inst1@psuse:~> db2
deactivate db test
DB20000I The DEACTIVATE DATABASE command completed successfully.
--数据库deactivate后,可以使用db2dart的DEMP(Dump
EMP的意思)选项来看EMP的信息。至于TSI和OI,你猜。
db2inst1@psuse:~>
db2dart test /demp /tsi 5 /oi 4
The requested DB2DART
processing has completed successfully!
Complete DB2DART report
found in:
/home/db2inst1/sqllib/db2dump/DART0000/TEST.RPT
--这个RPT的内容如下:
Action option: DEMP
Table-object-ID: 4;
Tablespace-ID: 5
Connecting to Buffer Pool
Services...
--这个数据库对象的EMP被倒出来了:
DART formatted EMP page
dump:
-----------------------------
Traversing extent map
for:
Object ID: 4
Table space: 5
Pool specific info:
-------------------
Name = TS1
Pool extent size
= 32
# of
containers = 1
Container names:
/home/db2inst1/db2inst1/NODE0000/TEST/TS1
Object specific mapping
info: --对象映射信息如下:
-----------------------------
DAT extent anchor:
160 --DB2告诉你这个对象的EMP在第160页。
--注意哦,这里的单位是页,160/32(extent size)=5。
--由于extent从0开始排序,所以这个对象的EMP在extent 4上。
--下面是这个extent里的信息,一个extent的大小是32页对不?
--所以下面的page就是从160到191页,刚好是32页大小。
Traversing extent map for
object type: 0
Tablespace ID: 5,
Tablespace Seed: 5, Object: 4 EMP page class: 64,
EMP pool page: 160, #
entries: 1
Page LSN =
0000000008B2812C
Pool relative page #'s
:
192
--这个192指明T2表的数据存在192页开始的extent上
--192/32=6,就是数据保存在了extent
5上。
Tablespace ID: 5,
Tablespace Seed: 5, Object: 4 EMP page class: 64,
EMP pool page: 161, #
entries: 0
Page LSN =
0000000008B280D4
Pool relative page #'s
:
(中间略,全一样)
EMP pool page: 190, #
entries: 0
Page LSN =
0000000008B280D4
Pool relative page #'s
:
Tablespace ID: 5,
Tablespace Seed: 5, Object: 4 EMP page class: 64,
EMP pool page: 191, #
entries: 0
Page LSN =
0000000008B280D4
Pool relative page #'s
:
--下面是和这个表有关的其他对象的extent映射信息。
INX extent anchor: 0
XDA extent anchor: 0
LF extent anchor: 0
LOB extent anchor: 0
LOBA extent anchor: 0
BKM extent anchor: 0
--下面我们继续实验,再造一些数据:
db2inst1@psuse:~> db2
connect to test
Database Connection
Information
Database
server = DB2/LINUXX8664 9.7.9
SQL authorization
ID = DB2INST1
Local database
alias = TEST
db2inst1@psuse:~> db2
"insert into t2 select * from t2"
DB20000I The SQL command completed successfully.
--重复执行,直到表空间被撑爆。
db2inst1@psuse:~> db2
"insert into t2 select * from t2"
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL
processing it returned:
SQL0289N Unable to allocate new pages in table space
"TS1". SQLSTATE=57011
db2inst1@psuse:~> db2
connect reset
DB20000I The SQL command completed successfully.
--再db2dart一次,内容如下:
Action option: DEMP
Table-object-ID: 4;
Tablespace-ID: 5
Connecting to Buffer Pool
Services...
DART formatted EMP page
dump:
-----------------------------
Traversing extent map
for:
Object ID: 4
Table space: 5
Pool specific info:
-------------------
Name = TS1
Pool extent size
= 32
# of
containers = 1
Container names:
/home/db2inst1/db2inst1/NODE0000/TEST/TS1
Object specific mapping
info:
-----------------------------
DAT extent anchor:
160 --没有大动作这里不会变咯。
Traversing extent map for
object type: 0
Tablespace ID: 5,
Tablespace Seed: 5, Object: 4 EMP page class: 64,
EMP pool page: 160, #
entries: 15
Page LSN =
0000000009F9CF2C
Pool relative page #'s
: --变化的地方在这里!
192 96 128 224 256
288 320 352 384 416
448 480 512 544 576
Tablespace ID: 5,
Tablespace Seed: 5, Object: 4 EMP page class: 64,
EMP pool page: 161, #
entries: 0
Page LSN =
0000000008B280D4
Pool relative page #'s
:
(中间略,全一样)
Tablespace ID: 5,
Tablespace Seed: 5, Object: 4 EMP page class: 64,
EMP pool page: 191, #
entries: 0
Page LSN =
0000000008B280D4
Pool relative page #'s
:
INX extent anchor: 0
XDA extent anchor: 0
LF extent anchor: 0
LOB extent anchor: 0
LOBA extent anchor: 0
BKM extent anchor: 0
实验可以看到,192之后多了一些数字,它们之间的差是1个extentsize,最大的是576,也就是说当我们写到576页时,DB2报告表空间满,576+32=608页,那么这个表空间的全部可用页数一定就是608页。
db2inst1@psuse:~> db2
"select tbsp_usable_pages from sysibmadm.tbsp_utilization where
tbsp_name='TS1'"
TBSP_USABLE_PAGES
--------------------
608
1 record(s) selected.
哦耶!