暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

表空间管理技术-本地管理表空间

eygle 2019-10-14
1373

从Oracle 8i开始,Oracle引入了一种全新的表空间管理方式:本地化管理表空间(Local Management Tablespace,简称LMT)。所谓本地化管理,就是指Oracle不再利用数据字典表来记录Oracle表空间里面的区间的使用状况,而是在每个表空间的数据文件的头部加入了一个位图区域,在其中记录每个Extent的使用状况。每当一个Extent被使用,或者被释放以供重新使用时,Oracle都会更新数据文件头部的这个记录,反映这个变化。


本地化管理的表空间的主要创建语法如下:

CREATE TABLESPACE tablespace_name
DATAFILE 'datafile_path_name'
[EXTENT MANAGEMENT { LOCAL
{AUTOALLOCATE | UNIFORM [SIZE INTETER [K|M] ] } } ]


其中关键字EXTENT MANAGEMENT LOCAL指定这是一个本地化管理的表空间。


在Oracle 8i中,创建表空间时字典管理还是默认的管理方式,在Oracle 9iR2中,本地管理表空间成为了默认的选项。需要记住的是,字典管理表空间作为一种过时的技术已经渐渐远去,本地管理表空间是一种更为高效的表空间管理技术。以上对于字典管理表空间的介绍是为了让大家更好地了解Oracle空间管理技术的来龙去脉。


需要注意的是,在创建本地管理表空间时,还可以选择更具体的空间分配方式:是选择自动分配(AUTOALLOCATE)还是统一尺寸(UNIFORM)。若为自动分配,则表明让Oracle来决定区块的使用办法,缺省地Oracle会按照递增算法来分配空间;如果选择统一尺寸,则还可以详细指定每个区间(Extent)的大小。


注意如果不指定Uniform Size的大小,Oracle默认为每个区分配1MB大小:

SQL> CREATE TABLESPACE eygle
  2  DATAFILE '/opt/oracle/oradata/eygle/eygle01.dbf' SIZE 10 m
  3  EXTENT MANAGEMENT LOCAL UNIFORM;
 
Tablespace created.
SQL> SELECT tablespace_name, extent_management, allocation_type
  2    FROM dba_tablespaces where tablespace_name='EYGLE';
TABLESPACE_NAME                EXTENT_MAN ALLOCATIO
------------------------------ ---------- ---------
EYGLE                          LOCAL      UNIFORM


这里介绍一个重要视图DBA_EXTENTS:

SQL> desc dba_extents
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 OWNER                                              VARCHAR2(30)
 SEGMENT_NAME                                       VARCHAR2(81)
 PARTITION_NAME                                     VARCHAR2(30)
 SEGMENT_TYPE                                       VARCHAR2(18)
 TABLESPACE_NAME                                    VARCHAR2(30)
 EXTENT_ID                                          NUMBER
 FILE_ID                                            NUMBER
 BLOCK_ID                                           NUMBER
 BYTES                                              NUMBER
 BLOCKS                                             NUMBER
 RELATIVE_FNO                                       NUMBER


这个视图记录了每个对象分配的区间(Extent),通过查询这个视图可以看到哪些对象分配了多少区间,以及区间具体位于的文件等信息:

SQL> select extent_id,block_id,blocks
  2  from dba_extents where segment_name='TEST' and tablespace_name='EYGLE';
 EXTENT_ID   BLOCK_ID     BLOCKS
---------- ---------- ----------
         0          9        128


在本地管理表空间的空间管理上,Oracle将存储信息保存在表空间头部的位图中,而不是保存在数据字典中。通过这样的方式,在分配或者回收空间的时候,表空间就可以独立地在数据文件头部完成操作而无需与其他对象打交道。


也因为仅仅操作数据文件头部几个数据块,不用操作数据字典,所以Oracle在本地管理的表空间中添加、删除段时,效率要比字典管理的表空间快,特别是在并发性很强的空间请求中。


注意到上面的测试数据,当初始创建第一张数据表时,分配的Block_ID是从第9个Block开始的,也就是说前8个Block都被系统保留了:

SQL> select extent_id,block_id,blocks
  2  from dba_extents where segment_name='TEST' and tablespace_name='EYGLE';
 EXTENT_ID   BLOCK_ID     BLOCKS
---------- ---------- ----------
         0          9        128


在本地管理的表空间中,如果数据库块大小(db_block_size)为16kB或16kB以下,数据文件头保留64kB空间;若是32kB的块大小,则保留128kB。即数据块大小和文件头保留的数据块块数之间的对应关系为:


db_block_size=2K,文件头会保留32个数据块;

db_block_size=4K,文件头会保留16个数据块;

db_block_size=8K,文件头会保留8个数据块;

db_block_size=16K,文件头会保留4个数据块;

db_block_size=32K,文件头会保留4个数据块;


对于默认8kB块大小的表空间,Oracle保留8个块用于管理,其中数据块1和2用于记录数据文件头信息,数据块3~8用于记录区间的位图信息。


可以通过DUMP方式来简单了解一下保留块所记录的内容。转储数据块信息可以使用如下命令:

alter system dump datafile x block max block_id block min block_id;


使用之前创建的表空间进行测试:

SQL> alter system dump datafile 3 block min 1 block max 3;
System altered.


通过gettrcname.sql脚本获得跟踪文件名称(11g中不再需要使用这个脚本):

SQL> SELECT a.VALUE || b.symbol || c.instance_name || '_ora_' || d.spid || '.trc' TRACE_FILE_NAME
  2    FROM (SELECT VALUE FROM v$parameter WHERE NAME = 'user_dump_dest') a,
  3         (SELECT SUBSTR (VALUE, -6, 1) symbol FROM v$parameter
  4           WHERE NAME = 'user_dump_dest') b,
  5         (SELECT instance_name FROM v$instance) c,
  6         (SELECT spid FROM v$session s, v$process p, v$mystat m
  7           WHERE s.paddr = p.addr AND s.SID = m.SID AND m.statistic# = 0) d
  8  /
TRACE_FILE_NAME
--------------------------------------------------------------------------------------
/opt/oracle/admin/eygle/udump/eygle_ora_1301.trc


检查生成的跟踪文件,可以发现,前两个Block记录的是文件头信息:

Start dump data blocks tsn: 4 file#: 3 minblk 1 maxblk 3
Block 1 (file header) not dumped: use dump file header command
buffer tsn: 4 rdba: 0x00c00002 (3/2)
scn: 0x0004.6c1e0b8a seq: 0x02 flg: 0x04 tail: 0x0b8a1d02
frmt: 0x02 chkval: 0x7648 type: 0x1d=KTFB Bitmapped File Space Header
File Space Header Block:
Header Control:
RelFno: 3, Unit: 128, Size: 1280, Flag: 1
AutoExtend: NO, Increment: 0, MaxSize: 0
Initial Area: 7, Tail: 1160, First: 1, Free: 8
Header Opcode:
Save: No Pending Op


注意这里oracle提示我们对于数据文件的第一个块应该用dump file header command,意思就是告诉我们应该用如下的专用于dump datafile header的命令来dump数据文件的第一个块:

alter session set events 'immediate trace name file_hdrs level <n>';


这里的level我们通常用10,意思为dump的内容会包含以下内容:

Control file’s datafile entry + generic file header + datafile header


这里摘录一段用上述dump命令dump出来的datafile header block(数据文件的第一个块)的具体内容:

DATA FILE #1:
  (name #7) /iprat01/oradata/ipra/system01.dbf
creation size=0 block size=8192 status=0xe head=7 tail=7 dup=1
 tablespace 0, index=1 krfil=1 prev_file=0
 unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00
 Checkpoint cnt:7030 scn: 0x076e.6ba74f65 05/31/2010 03:00:40
 Stop scn: 0xffff.ffffffff 05/28/2010 21:56:50
 Creation Checkpointed at scn:  0x0000.00000008 07/22/2005 00:42:44
 thread:0 rba:(0x0.0.0)
 enabled  threads:  00000000 00000000 00000000 00000000 00000000 00000000
  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  ……省略显示部分内容
  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  00000000 00000000 00000000 00000000 00000000 00000000
 Offline scn: 0x0000.00086982 prev_range: 0
 Online Checkpointed at scn:  0x0000.00086983 11/14/2007 16:18:40
 thread:1 rba:(0x1.2.0)
 enabled  threads:  01000000 00000000 00000000 00000000 00000000 00000000
  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  ……省略显示部分内容
  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  00000000 00000000 00000000 00000000 00000000 00000000
 Hot Backup end marker scn: 0x0000.00000000
 aux_file is NOT DEFINED
 V10 STYLE FILE HEADER:
     Compatibility Vsn = 169869568=0xa200100
     Db ID=622427550=0x25197d9e, Db Name='IPRA'
     Activation ID=0=0x0
     Control Seq=193563=0x2f41b, File size=61440=0xf000
     File Number=1, Blksiz=8192, File Type=3 DATA
Tablespace #0 - SYSTEM  rel_fn:1
Creation   at   scn: 0x0000.00000008 07/22/2005 00:42:44
Backup taken at scn: 0x0000.00000000 01/01/1988 00:00:00 thread:0
 reset logs count:0x2610e3e0 scn: 0x0000.00086983 reset logs terminal rcv data:0x0 scn: 0x0000.00000000
 prev reset logs count:0x21a23e71 scn: 0x0000.00000001 prev reset logs terminal rcv data:0x0 scn: 0x0000.00000000
 recovered at 05/16/2008 11:47:40
 status:0x2004 root dba:0x00400179 chkpt cnt: 7030 ctl cnt:7029
begin-hot-backup file size: 0
Checkpointed at scn:  0x076e.6ba74f65 05/31/2010 03:00:40
 thread:1 rba:(0x1a0a.2.10)
 enabled  threads:  01000000 00000000 00000000 00000000 00000000 00000000
  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  ……省略显示部分内容
  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  00000000 00000000 00000000 00000000 00000000 00000000
Backup Checkpointed at scn:  0x0000.00000000
 thread:0 rba:(0x0.0.0)
 enabled  threads:  00000000 00000000 00000000 00000000 00000000 00000000
  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  ……省略显示部分内容
  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  00000000 00000000 00000000 00000000 00000000 00000000
External cache id: 0x0 0x0 0x0 0x0
Absolute fuzzy scn: 0x0000.00000000
Recovery fuzzy scn: 0x0000.00000000 01/01/1988 00:00:00
Terminal Recovery Stamp  01/01/1988 00:00:00
Platform Information:   Creation Platform ID: 6
Current Platform ID: 6 Last Platform ID: 6


从第3个块开始,Oracle记录了位图信息:

buffer tsn: 4 rdba: 0x00c00003 (3/3)
scn: 0x0004.6c1e0b8a seq: 0x01 flg: 0x04 tail: 0x0b8a1e01
frmt: 0x02 chkval: 0x8332 type: 0x1e=KTFB Bitmapped File Space Bitmap
File Space Bitmap Block:
BitMap Control:
RelFno: 3, BeginBlock: 9, Flag: 0, First: 1, Free: 63487
0100000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
……


注意这里的01是十六进制,转换为二进制就是0000 0001,按照oracle看bitmap的惯例(以每个byte为一组,组与组之间是从左往右读,但组内是从右往左读),这样翻译过来就是10000000,即used, free, free, free, free, free, free, free.,也就是代表已经分配了一个区间。


如果再分配一个区间:

SQL> alter table eygle.test allocate extent;
Table altered.
SQL> select file_id,extent_id,block_id,blocks
  2  from dba_extents where segment_name='TEST' and tablespace_name='EYGLE';
   FILE_ID  EXTENT_ID   BLOCK_ID     BLOCKS
---------- ---------- ---------- ----------
         3          0          9        128
         3          1        137        128


那么此时的位图变成了:

buffer tsn: 4 rdba: 0x00c00003 (3/3)
scn: 0x0004.6c1e1858 seq: 0x01 flg: 0x00 tail: 0x18581e01
frmt: 0x02 chkval: 0x0000 type: 0x1e=KTFB Bitmapped File Space Bitmap
File Space Bitmap Block:
BitMap Control:
RelFno: 3, BeginBlock: 9, Flag: 0, First: 2, Free: 63486
0300000000000000 0000000000000000 0000000000000000 0000000000000000


这里的03代表0000 0011,经过转换也就是1100 0000,正是代表已经分配了2个区间,所以oracle这里需要free extent的时候是从第3个extent开始扫描(0,1都已经被用了),这也和我们从dba_extents里看到的结果一致。

通过进一步的测试来看一下空间的回收等记录信息,再创建一个测试表,并分配3个区间:

SQL> create table eygle.test2 as select * from dba_objects;
Table created.
SQL> alter table eygle.test2 allocate extent;
Table altered.
SQL> alter table eygle.test2 allocate extent;
Table altered.
SQL> alter table eygle.test2 allocate extent;
Table altered.


加上初始创建分配的一个区间,此时对象test2紧跟test对象共占有4个区间:

SQL> select file_id,extent_id,block_id,blocks
  2  from dba_extents where file_id=3;
   FILE_ID  EXTENT_ID   BLOCK_ID     BLOCKS
---------- ---------- ---------- ----------
         3          0          9        128
         3          1        137        128
         3          0        265        128
         3          1        393        128
         3          2        521        128
         3          3        649        128
 
6 rows selected.


这时转储一下文件头可以发现区间位图已经变化为:

RelFno: 3, BeginBlock: 9, Flag: 0, First: 6, Free: 63482
3F00000000000000 0000000000000000 0000000000000000 0000000000000000


3F转换为二进制是0011 1111,经过位交换结果是1111 1100,也就是对应了前6个已经分配的区间。继续创建第三个对象test3:

SQL> create table eygle.test3 as select * from dba_objects;
Table created.


此时位图变化为:

RelFno: 3, BeginBlock: 9, Flag: 0, First: 7, Free: 63481
7F00000000000000 0000000000000000 0000000000000000 0000000000000000


7F对应二进制为0111 1111,经过位交换结果为1111 1110,也就是对应了前7个已经分配的区间。此时DROP掉第二个对象test2:

SQL> drop table eygle.test2;
 
Table dropped.
 
SQL> col segment_name for a20
SQL> select segment_name,file_id,extent_id,block_id,blocks
  2  from dba_extents where file_id=3;
 
SEGMENT_NAME            FILE_ID  EXTENT_ID   BLOCK_ID     BLOCKS
-------------------- ---------- ---------- ---------- ----------
TEST                          3          0          9        128
TEST                          3          1        137        128
TEST3                         3          0        777        128


此时位图变化为:

RelFno: 3, BeginBlock: 9, Flag: 0, First: 2, Free: 63485
4300000000000000 0000000000000000 0000000000000000 0000000000000000


43对应二进制为0100 0011,经过位交换的结果为1100 0010,也就是文件3的第3~6个区间已经释放。通过这样的位图变化,Oracle就将以前复杂的字典维护变为效率更高的位图维护,从而全面提升了性能。


简单提一下的是,在自动分配的本地管理的表空间中,区间大小可能由以下尺寸组成64kB、1MB、8MB、64MB甚至是256MB。但是不管多大,都有一个通用尺寸64kB,所以64kB就是该表空间的一个位标记的大小。


Oracle推出的这种新的表空间管理方法具有一系列的优点,相应地解决了字典管理表空间技术面临的难题,从而迅速地取代了传统的DMT技术,本地管理表空间技术的主要优点如下。


· 通过位图代替字典管理。本地管理的表空间用数据文件头部的位图块来记录和管理空间的分配和回收,避免了递归的空间管理操作,从而避免了字典操作以及因为字典操作而带来的性能问题。

· 避免了碎片问题及空间浪费。本地化管理可以通过UNIFORM或AUTOALLOCATE的方式进行区间管理,通过对Extent进行UNIFORM约定,传统的空间碎片问题得以解决,进而空间的分配效率也大大提高。


正因为本地管理表空间技术的卓越性能,我们已经可以放心地将DMT称之为过去时了。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论