ORACLE物理和逻辑结构层次图
注意看这个符号,代表包含关系一对多的关系
Oracle 数据库体系结构由数据库的逻辑结构和物理结构构成
物理:ORACLE是个基于OS的软件,所以OS的东西被称为物理,能通过操作系统看到的.
右边是物理结构,包括构成数据库的控制文件联机重做日志文件和数据文件
逻辑:在ORACLE内部使用的对象,不能呈现在操作系统上的,都属于逻辑
左边是逻辑结构,层次从大到小包括数据库、表空间、段、区和数据块
逻辑结构间由上到下是层层包含
逻辑结构与物理结构的关系
一个表空间由多个数据文件组成
一个数据文件由多个区组成
一个数据文件由多个操作系统块组成
一个数据库块由多个操作系统块组成
虽然物理结构和逻辑结构是分开理解的,但是他们还是有联系的
ORACLE的段、区、块之间关系
段segment与物理结构的关系
一个堆表所占用所有物理空间,这里的"所有物理空间"就指的是一个段.(分区表除外,分区表有多个段)
段是占有一定存储空间的对象 可以理解为是对占用空间的对象的另一种命名方法
表是段,索引也是段,上图可以看到段可以跨越多个数据文件
一个表空间由一个或多个段组成 一个段由一个或多个区组成
我们平常用的表是无序存放的,所以叫堆表,而索引是有序存放的.这是表和索引最大的区别
[表空间]
一个表空间在某一时刻只能属于一个数据库
每个表空间由一个或多个数据文件组成
表空间可以由一个或多个段组成
[数据文件]
Oracle 数据库内的每个表空间由一个或者多个数据文件组成
一个数据文件只能属于一个表空间
创建数据文件时,通过分配指定数量的磁盘空间,加上文件系统头的少量的开销,来创建表空间数据文件。
[段]
表空间可以由一个或多个段组成
每个段由一个或多个区组成
[区]
一个或多个区组成一个段
当段创建后它至少由一个区组成
随着段的增长,将向该段添加区
一个区就是一组连续的 Oracle 块
[ORACLE块]
Oracle 数据块是 Oracle能够读或写的最小存储单元,但不是最小分配单元
一个数据块对应一个或多个(被分配了数据文件的)操作系统块组成
数据块大小应当是操作系统块大小的整数倍,以避免不必要的I/O
它们之间的关系好比是一个住宅小区
一个小区是由一栋栋楼组起来的
每一栋楼是由一层层楼组成
每一层楼是每一户组成
住宅小区就是段
段可以占多个数据文件 住宅小区可以有东区和西区
每一栋楼就是一个区
区是连续的块
每一户就是一个块
一个段能跨越表空间吗?
一个段能跨越属于同一表空间的不同数据文件吗?
一个区能跨越属于同一表空间的不同数据文件吗?
ORACLE数据库的数据块大小由初始化参数DB_BLOCK_SIZE在创建库时指定,
指定后不能再修改,那控制文件、数据文件是基于ORACLE的数据块大小还是基于OS的块大小?
控制文件大小和oracle块有什么关系?
那日志文件是基于OS块大小还是ORACLE数据块大小?
空间的分配和管理
所有这些空间分配的管理就引出了我们下面两大概念
字典管理表空间 DMT
本地管理表空间 LMT
表空间中的空间管理 DMT LMT
本地管理的表空间LMT
在表空间中管理空闲区
使用位图(bitmap)记录空闲区
位图中每一位(bit)对应于一个块或一组块
位图的位(bit)值指示空闲或使用
字典管理的表空间DMT
由数据字典管理空闲区
分配或取消分配区后更新相应的基表
字典管理的表空间DMT
每当区分配或回收时Oracle将更新数据字典中的相应表
使用的空间由 UET$ (USED EXTENT TABLE) 表管理
空闲的空间由 FET$ (FREE EXTENT TABLE) 表管理
我们对表做insert或delete就要来更新这两个表
其实只要数据容量产生变化,这两个表都要动,并且这两个表时联动的.
频繁的做DML动作 DML将产生UNDO 这两个表的联动性非常影响性能
这就是原来最早的空间分配的区管理模式
本地管理的表空间LMT
在8.1.5后字典管理被新的管理方法取代,我们称为本地管理表空间
管理自身区的表空间在每个数据文件内都维护一个位图
以了解该数据文件内块的空闲或使用状态
Oracle 服务器更改位图数值以显示块的新状态 这个更改不涉及到UNDO
就算中途INSERT时申请区完后ROLLBACK 这个区的申请不会退还回去,因为它不需要做UNDO
位图管理的样子
左边块号 1-53个块
1号是数据文件头
2号是文件位图头 位图控制部分
3-33都是位图块
34-38 第一业务数据区
39-43 第二业务数据区
44-48 第三业务数据区
49-53 第四业务数据区
图中:每一个位图管理一个或多个数据块,每一个位图管理一个区域(5个块)
每一个位图块内用16进制表示 将16进制转成二进制 再将二进制反转(前4位和后4位兑换) 1就代表使用 0就代表没使用
第三个块就是位图块,第一个字节值是 0F 是16进制表示.也就是二进制的00001111
转换对照图
再将二进制的00001111反转 11110000
于是得到结果
前4个区域被使用中
后4个区域没有被使用
当第一个区域被释放 就会变成01110000
反转举例 比如块号8是位图,它的内容0F 1D 5C 反转后得到 11110000 11010001 11000101
0F=> 00001111 => 11110000
1D=> 00011101 => 11010001
5C=> 01011100 => 11000101
选择一种空间管理方法
表空间区可以通过数据字典表或者位图管理在创建表空间时选择其中一种
字典管理因其管理模式要付出昂贵代价 已经成为历史
9I和10G默认是本地管理表空间方式
SQL> select TABLESPACE_NAME,EXTENT_MANAGEMENT from dba_tablespaces;
TABLESPACE_NAME EXTENT_MAN
--------------- ----------
SYSTEM LOCAL
UNDOTBS1 LOCAL
SYSAUX LOCAL
TEMP LOCAL
USERS LOCAL
UNDOTBS2 LOCAL
MYTBS LOCAL
UNDO2 LOCAL
8 rows selected.
SQL>
本地管理的好处
减少了数据字典的冲突,因为区的分配不需要记录UET$,FET$
当执行事务时(如INSERT大量数据) 一旦申请了区,即使执行回滚操作
也不需要把区释放回去,因为空间分配和释放没有UNDO生成
不需要SMON整理区碎片。
减少空间递归管理,这是本地管理最重要的出发点。
递归SQL 就是我们执行一条SQL,会使oracle在后台执行多条SQL,这个牵扯的多条SQL就是递归SQL
创建表空间时区管理方式语法
uniform. 就是区的大小都是一样的
autoallocate 是自动分配的
SQL> drop tablespace mytbs including contents and datafiles;
Tablespace dropped.
SQL> create tablespace mytbs datafile '/u01/oracle/oradata/ora10g/mytbs01.dbf' size 100M;
Tablespace created.
SQL> select dbms_metadata.get_ddl('TABLESPACE','MYTBS') from dual;
DBMS_METADATA.GET_DDL('TABLESPACE','MYTBS')
--------------------------------------------------------------------------------
CREATE TABLESPACE "MYTBS" DATAFILE
'/u01/oracle/oradata/ora10g/mytbs01.dbf' SIZE 104857600
LOGGING ONLINE PERMANENT BLOCKSIZE 8192
EXTENT MANAGEMENT LOCAL AUTOALLOCATE SEGMENT SPACE MANAGEMENT AUTO
SQL>
SQL> drop table t1 purge;
Table dropped.
SQL> create table t1 tablespace mytbs as select * from scott.emp;
Table created.
SQL>
SQL> select segment_name,extent_id,file_id,block_id,blocks from dba_extents where wner='SYS' and SEGMENT_NAME='T1';
SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
------------------------- ---------- ---------- ---------- ----------
T1 0 5 9 8
连续插入 数据翻倍
SQL> insert into t1 select * from t1;
448 rows created.
SQL> select segment_name,extent_id,file_id,block_id,blocks from dba_extents where wner='SYS' and SEGMENT_NAME='T1';
SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
------------------------- ---------- ---------- ---------- ----------
T1 0 5 9 8
T1 1 5 17 8
SQL>
连续插入 数据翻倍
SQL> insert into t1 select * from t1;
14336 rows created.
SQL> select segment_name,extent_id,file_id,block_id,blocks from dba_extents where wner='SYS' and SEGMENT_NAME='T1';
SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
------------------------- ---------- ---------- ---------- ----------
T1 0 5 9 8
T1 1 5 17 8
T1 2 5 25 8
T1 3 5 33 8
T1 4 5 41 8
T1 5 5 49 8
T1 6 5 57 8
T1 7 5 65 8
T1 8 5 73 8
T1 9 5 81 8
T1 10 5 89 8
T1 11 5 97 8
T1 12 5 105 8
T1 13 5 113 8
T1 14 5 121 8
T1 15 5 129 8
T1 16 5 137 128
17 rows selected.
SQL>
连续插入 数据翻倍
SQL> insert into t1 select * from t1;
917504 rows created.
SQL> select segment_name,extent_id,file_id,block_id,blocks from dba_extents where wner='SYS' and SEGMENT_NAME='T1';
SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
------------------------- ---------- ---------- ---------- ----------
T1 0 5 9 8
T1 1 5 17 8
T1 2 5 25 8
T1 3 5 33 8
T1 4 5 41 8
T1 5 5 49 8
T1 6 5 57 8
T1 7 5 65 8
T1 8 5 73 8
T1 9 5 81 8
T1 10 5 89 8
T1 11 5 97 8
T1 12 5 105 8
T1 13 5 113 8
T1 14 5 121 8
T1 15 5 129 8
T1 16 5 137 128
.....
T1 77 5 7945 128
T1 78 5 8073 128
T1 79 5 8201 1024
T1 80 5 9225 1024
T1 81 5 10249 1024
82 rows selected.
SQL>
两个分配终止大小位置
SQL> select 16*8*8192/1048576||'M' from dual;
16
--
1M
SQL> select (16*8+63*128)*8192/1048578||'M' from dual;
(16*8+63*128)*8192/1048578||'M'
-----------------------------------------
63.9998779299203301995655068101753040785M
SQL>
再测试uniform如何分配
CREATE TABLESPACE "MYTBS2" DATAFILE
'/u01/oracle/oradata/ora10g/mytbs02.dbf' SIZE 104857600
LOGGING ONLINE PERMANENT BLOCKSIZE 8192
EXTENT MANAGEMENT LOCAL uniform. size 64K SEGMENT SPACE MANAGEMENT AUTO;
SQL> create table t2 tablespace mytbs2 as select * from scott.emp;
Table created.
SQL>
SQL> insert into t2 select * from t2;
896 rows created.
SQL> select segment_name,extent_id,file_id,block_id,blocks from dba_extents where wner='SYS' and SEGMENT_NAME='T2';
SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
------------------------- ---------- ---------- ---------- ----------
T2 0 6 9 8
T2 1 6 17 8
SQL>
SQL> insert into t2 select * from t2;
14336 rows created.
SQL> select segment_name,extent_id,file_id,block_id,blocks from dba_extents where wner='SYS' and SEGMENT_NAME='T2';
SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
------------------------- ---------- ---------- ---------- ----------
T2 0 6 9 8
T2 1 6 17 8
T2 2 6 25 8
T2 3 6 33 8
T2 4 6 41 8
T2 5 6 49 8
T2 6 6 57 8
T2 7 6 65 8
T2 8 6 73 8
T2 9 6 81 8
T2 10 6 89 8
T2 11 6 97 8
T2 12 6 105 8
T2 13 6 113 8
T2 14 6 121 8
T2 15 6 129 8
T2 16 6 137 8
T2 17 6 145 8
T2 18 6 153 8
T2 19 6 161 8
T2 20 6 169 8
T2 21 6 177 8
T2 22 6 185 8
23 rows selected.
SQL>
空间回收(整理碎片)
10G以前 回收的方法
1. 在表空间中移动表
alter table TABLE_NAME move tablespace TABLESPACE_NAME;
2. 将数据导出 删除表 再将数据导入
10G中提供的新方法
alter table TABLE_NAME shrink space [compact|cascate]
alter table TABLE_NAME shrink space; 整理碎片并回收空间
alter table TABLE_NAME shrink space compact; 只整理碎片 不回收空间
alter table TABLE_NAME shrink space cascate; 整理碎片回收空间 并连同表的级联对象一起整理(比如索引)
使用条件
自动段管理模式
打开行移动
使用步骤
1. alter table t1 enable ROW MOVEMENT;
2. shrink 操作
3. alter table t1 disable ROW MOVEMENT;
段空间管理语法
AUTO 就是ASSM
MANUAL 就是MSSM
分配的管理方法
ASSM是自动段管理 AUTO SEGMENT SPACE MANAGEMENT
MSSM是手工段管理
FREELIST(空闲列表)管理
/ ASSM ---> BITMAP
LMT
\ MSSM ---\
DMT ----------- FREELIST
FREE extent可以分配给不同的段
extent的使用和空闲由数据文件位图或者数据字典UET$和FET$来管理
而在属于段内的块如何来管理呢?
在字典管理及本地管理非自动段管理时 将由FREELIST和FREELIST组来管理
在本地管理表空间的自动段管理采用位图来管理
FREELIST管理
FREELIST作为一个Oracle存储管理的核心参数
其行为方式由Oracle内部控制
但对这种机制不了解时,会遇到很多问题
当插入一条记录,会插入到哪个块中?
是使用新块,还是插入有数据的老块?
段是什么时候扩展的,如何扩展的?
表中只有一条记录,但是做一次select时,代价为何却是上千个块?
带着这些问题 来了解FREELIST
块的内部结构
header中包含:
块属性信息,事务信息,表目录,行目录
属性信息:
块的类型,块的格式,块地址,SCN,块的序列号,块的标志
事务信息:
事务相关的基本信息,和ITL(事务槽)
表目录:
当前表的信息
行目录:
记录块内存储行的地址信息
free space:
空闲空间
data space:
使用空间
在生成段的时候,会同时分配初始区(initial extents),
初始区的第一个块就格式化为segment header,
并被用来记录free list描述信息、extents信息,HWM信息等。
段头就是初始区的第一个块
free list是一种单向链表用于定位可以接收数据的块,
在字典管理方式的表空间中或MSSM,Oracle使用free list来管理未分配的存储块。
Oracle记录了有空闲空间的块用于insert或Update。空闲空间来源于两种方式:
1.段中所有超过高水位(HWM)的块,这些块已经分配给段了,但是还未被使用。
2.段中所有在HWM下的且链入了free list的块,可以被重用。
HWM:HIGH WATER MARK代表一个表使用的最大的(top limit)块 。
简单点说 HWM 就是一口井曾经达到的最高水位,也就是历史最高水位点
比如一个杯子能装100升水 装到80,倒出20 . 高水位就是80;
空闲的块怎么来的?
1.段中所有超过HWM的块,这些块已经分配给段了,但是还未被使用。
注意限定词:这些块已经分配给段了
2.段中所有在HWM下的且链入了free list的块,可以被重用。
FREE LIST就是一个链入了空闲块的单向链表
高水位上的肯定是空闲的,想用高水位以上的空闲之前,必须将高水位延伸.
SQL> drop tablespace mytbs including contents and datafiles;
Tablespace dropped.
SQL> CREATE TABLESPACE "MYTBS" DATAFILE '/u01/oracle/oradata/ora10g/mytbs01.dbf' SIZE 10M SEGMENT SPACE MANAGEMENT MANUAL;
Tablespace created.
SQL>
SQL> create table t1 tablespace mytbs as select * from scott.emp where 0=9;
Table created.
SQL> select segment_name,extent_id,file_id,block_id,blocks from dba_extents where wner='SYS' and SEGMENT_NAME='T1' ;
SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
------------------------- ---------- ---------- ---------- ----------
T1 0 5 9 8
SQL> alter system dump datafile 5 block 9;
System altered.
SQL> select c.value || '/' || d.instance_name || '_ora_' || a.spid || '.trc' trace
from v$process a,v$session b,v$parameter c,v$instance d
where a.addr=b.paddr and b.audsid=userenv('sessionid') and c.name= 'user_dump_dest';
TRACE
----------------------------------------------------------------------------------------------------
/u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
SQL> ! grep -a -A 14 'Extent Control Header' /u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 7
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x0140000a 高水位的位置 ext#: 0 blk#: 0 ext size: 7
#blocks in seg. hdr's freelists: 0 freelist链表中没有空闲数据块
#blocks below: 0 --HWM标志下没有数据块
mapblk 0x00000000 offset: 0
Unlocked
Map Header:: next 0x00000000 #extents: 1 obj#: 51407 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 0
SQL>
SQL> insert into t1 select * from scott.emp;
14 rows created.
SQL> alter system dump datafile 5 block 9;
SQL> ! grep -a -A 14 'Extent Control Header' /u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
--
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 7
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x0140000b 高水位的位置被推进 ext#: 0 blk#: 1 使用一个块 ext size: 7
#blocks in seg. hdr's freelists: 1 freelist链表中有一个空闲块可用
#blocks below: 1 --HWM标志下有一个数据块
mapblk 0x00000000 offset: 0
Unlocked
Map Header:: next 0x00000000 #extents: 1 obj#: 51407 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 1
SQL>
SQL> insert into t1 select * from t1;
112 rows created.
SQL> alter system dump datafile 5 block 9;
System altered.
SQL>
--
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 7
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x0140000c 高水位的位置持续推进 ext#: 0 blk#: 2 一个装不下 拓展一个新块 ext size: 7
#blocks in seg. hdr's freelists: 1 freelist链表中有一个空闲块可用
#blocks below: 2 --HWM标志下有2个数据块
mapblk 0x00000000 offset: 0
Unlocked
Map Header:: next 0x00000000 #extents: 1 obj#: 51410 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 2
SQL>
SQL> insert into t1 select * from t1;
224 rows created.
SQL> alter system dump datafile 5 block 9;
System altered.
SQL> ! grep -a -A 14 'Extent Control Header' /u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
--
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 7
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x0140000d 高水位的位置持续推进 ext#: 0 blk#: 3 两个装不下 拓展一个新块 ext size: 7
#blocks in seg. hdr's freelists: 1 freelist链表中有一个空闲块可用
#blocks below: 3 --HWM标志下有3个数据块
mapblk 0x00000000 offset: 0
Unlocked
Map Header:: next 0x00000000 #extents: 1 obj#: 51410 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 3
SQL>
SQL> insert into t1 select * from t1;
448 rows created.
SQL> alter system dump datafile 5 block 9;
System altered.
SQL> ! grep -a -A 14 'Extent Control Header' /u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
--
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 7
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x01400011 高水位的位置持续推进 ext#: 0 blk#: 7 拓展4个新块 ext size: 7
#blocks in seg. hdr's freelists: 2 freelist链表中有2个空闲块可用
#blocks below: 7 --HWM标志下有7个数据块
mapblk 0x00000000 offset: 0
Unlocked
Map Header:: next 0x00000000 #extents: 1 obj#: 51410 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 6
SQL>
SQL> insert into t1 select * from t1;
896 rows created.
SQL> select segment_name,extent_id,file_id,block_id,blocks from dba_extents where wner='SYS' and SEGMENT_NAME='T1' ;
SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
------------------------- ---------- ---------- ---------- ----------
T1 0 5 9 8
T1 1 5 17 8
SQL> alter system dump datafile 5 block 9;
System altered.
SQL> ! grep -a -A 14 'Extent Control Header' /u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
--
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 2 #blocks: 15
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x01400016 ext#: 1 拓展了一个新的extent blk#: 5 ext size: 8
#blocks in seg. hdr's freelists: 2
#blocks below: 12
mapblk 0x00000000 offset: 1
Unlocked
Map Header:: next 0x00000000 #extents: 2 拓展的次数 obj#: 51410 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
0x01400011 length: 8
SQL>
SQL> delete t1 where deptno=10;
384 rows deleted.
SQL> alter system dump datafile 5 block 9;
System altered.
SQL> ! grep -a -A 15 'Extent Control Header' /u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
--
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 2 #blocks: 15
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x01400016 delete数据删除 高水位没回收 ext#: 1 blk#: 5 ext size: 8
#blocks in seg. hdr's freelists: 2
#blocks below: 12
mapblk 0x00000000 offset: 1
Unlocked
Map Header:: next 0x00000000 #extents: 2 obj#: 51410 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
0x01400011 length: 8
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 7
SQL>
SQL> truncate table t1;
Table truncated.
SQL> alter system dump datafile 5 block 9;
System altered.
SQL> ! grep -a -A 15 'Extent Control Header' /u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
--
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 7
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x0140000a truncate截断 表恢复成初始化状态 ext#: 0 blk#: 0 ext size: 7
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Disk Lock:: Locked by xid: 0x0017.004.0000000c
Map Header:: next 0x00000000 #extents: 1 obj#: 51411 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 0
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
SQL>
SQL> drop table t1;
Table dropped.
SQL> alter system dump datafile 5 block 9;
System altered.
SQL> ! grep -a -A 15 'Extent Control Header' /u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
-- drop只是表放到回收站了 块内信息依然存在
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 7
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x0140000a ext#: 0 blk#: 0 ext size: 7
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Unlocked
Map Header:: next 0x00000000 #extents: 1 obj#: 51411 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 0
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
SQL>
SQL> purge recyclebin;
Recyclebin purged.
SQL> alter system dump datafile 5 block 9;
System altered.
SQL> ! grep -a -A 15 'Extent Control Header' /u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
--
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 7
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x0140000a ext#: 0 blk#: 0 ext size: 7
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Disk Lock:: Locked by xid: 0x0017.000.0000000c
Map Header:: next 0x00000000 #extents: 1 obj#: 51411 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 0
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
SQL>
SQL> create table d1 tablespace mytbs as select * from scott.dept;
Table created.
SQL> select segment_name,extent_id,file_id,block_id,blocks from dba_extents where wner='SYS' and SEGMENT_NAME='D1' ;
SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
------------------------- ---------- ---------- ---------- ----------
D1 0 5 9 8
SQL> alter system dump datafile 5 block 9;
System altered.
SQL> ! grep -a -A 15 'Extent Control Header' /u01/oracle/admin/ora10g/udump/ora10g_ora_3094.trc
-- 创建个新的对象 对象ID变了.一切重新开始重用
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 7
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x0140000b ext#: 0 blk#: 1 ext size: 7
#blocks in seg. hdr's freelists: 0
#blocks below: 1
mapblk 0x00000000 offset: 0
Unlocked
Map Header:: next 0x00000000 #extents: 1 obj#: 51414 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0140000a length: 7
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 0
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
SQL>
Freelist Link and Unlink 操作
就是链表的入表和出表动作
free list是一种单向链表用于定位可以接收数据的块
Freelist 按后进先出队列(LIFO) 方式管理。也就是说最后被link到freelist的块拥有最先unlink的机会
link表示有段的块要标志为空闲了
unlink表示有段的块要被其他进程用了
FREELIST的PCT_FREE与PCT_USED参数一起来标识可供插入操作使用的数据块;
每个块在INSERT或UPDATE操作(增大操作)后,数据库比较该数据块中的剩余自由空间与该段的PCT_FREE设置。
如果该数据块具有少于PCT_FREE的空闲空间(也就是说该块还未满,并非真正意义的满) 那么继续使用
如果该数据块具有达到PCT_FREE的空闲空间 (也就是说该块已满,并非真正意义的满) 那么这个块不能再插新数据
比如PCT_FREE本来是 10% 你批量插入数据后 数据块的使用空间90%了
数据库就从FREELIST上把这个块摘下来,而且该块不能再用于插入操作。
剩余的空闲空间保留给可能会增大该数据块中原来行大小的更新操作。
(比如原来有一个字符 update改成三个字符 另外两个字符就去占这个PCT_free)
同样,每个块在DELETE or UPDATE 操作(减小操作)之后,
如果数据块的已使用空间少于PCTUSED,则该数据块被认为空得足够插入操作使用
块将再次link到free list中
每次块加入free list时,都是link到链表的头部。
在字典管理DMT及MSSM时,我们将由FREELIST和FREELIST组来管理,
虽然我们可以通过设置FREELIST参数定义多个PROCESS FREELIST,降低BUFF 等待的可能
但是对FREELIST的争用频繁的现象仍然一直比较严重。
默认值 PCT_FREE 10%
PCT_USED 40%
SQL> create table e1 tablespace system pctfree 20 pctused 30 storage(freelists 2) as select * from scott.emp;
SQL> select TABLESPACE_NAME,TABLE_NAME,PCT_FREE,PCT_USED,FREELISTS from dba_tables where table_name in ('E1','D1','EMP');
TABLESPACE_NAME TABLE_NAME PCT_FREE PCT_USED FREELISTS
--------------- ------------------------- ---------- ---------- ----------
USERS EMP 10
SYSTEM E1 20 30 2
MYTBS D1 10 40 1
SQL>
EMP表没有值 说明不是手动管理的 是ASSM
自动段管理ASSM
从ORACLE 9.2版本开始,引入了一种新的段空间管理方式,称为ASSM,自动段管理
自动段管理,采用位图方式管理段空间。
位图段结构
ASSM --通过位图分成3级树结构的位图块来管理空闲块:L1 L2 L3
L3是ROOT层,放在段头,L2是分支层,而L1就是实际的位图块。
通过这种树结构技术结合位图,将大大缓解并发的压力。
我们再看来看下ASSM的工作情况
这图很重要 表示了块空间在ASSM中的情况。
里面4个图,从左到右看。
ASSM将采用把数据块拆分成4个水位:
0-25%,26%-50%,51%-75%,76%-100%
根据实际数据在4个水位的相对位置及PCTFREE来决定该块的空闲状况
注意ASSM中PCTUSED参数将无效 只用这四个水位来决定块被使用情况
上图我们看到设置的PCTFREE为40%(表示块得保留40%的块空闲空间,用作以后增大的UPDATE)
我们从左到右把上图分解为4个小图A B C D
A图的水位在PCTFREE规定的范围内,所以块当前的状态为FULL=NO
然后进行了INSERT 操作,有数据插入了块,水位升高了,达到PCTFREE线以上
这时,数据块状态直接变为了FULL=YES (B图)
FULL=YES代表什么呢?
代表你以后再执行INSERT语句时候,就不会将数据插入这个块中了,会找其他FULL=NO的块。
在B图后,执行DELETE到C图,这里要注意的是:
DELETE后水位仍然在50%以上,C图块的状态改变还是YES.
C图块的状态改变了没有?
因为块被分成了4个水位 0-25%,26%-50%,51%-75%,76%-100%
C这里虽然减少了,但是还没有跨越水平线
这样的好处是,减少频繁的改变块状态。防止系统颠簸
图D,DELETE操作后,水位下降到了26%-50%,这时候块状态发现改变了 又可以插入数据了
有了上图理论再分析下图
存储参数:
虽然表空间提供了这些存储参数 单不实用 因为自动分配模式无法使用这些参数
通常我们都是在建立表时将这些属性直接应用到表上 而不是表空间上
STORAGE(
INITIAL 65536
NEXT 1048576
MINEXTENTS 1
MAXEXTENTS 2147483645
)
什么时候需要改变这些参数?
比如你要向一个表中批量插入数据 默认分配每次都分的很小 批量就会导致分配很多次 影响加载速度
这时就可以将初始大小和下一次拓展的大小的值放大
dump 一级位图段头块
SQL> create tablespace abc datafile '/u254/abc01.dbf' size 10M;
Tablespace created.
SQL> drop table t1 purge;
Table dropped.
SQL> create table t1 tablespace abc as select * from scott.emp;
Table created.
SQL> select segment_name,extent_id,file_id,block_id,blocks from dba_extents where wner='SYS' and SEGMENT_NAME='T1';
SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
------------------------- ---------- ---------- ---------- ----------
T1 0 6 9 8
SQL> alter system dump datafile 6 block 9;
System altered.
SQL>
查trc文件找到 FIRST LEVEL BITMAP BLOCK
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24756465/viewspace-717784/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/24756465/viewspace-717784/