Oracle教程Storage Structure
1.存储结构简介
Oracle数据库由物理存储结构和逻辑存储结构组成。
物理存储结构由操作系统的文件组成,例如:数据文件,日志文件,控制文件等。物理存储结构是oracle内部的组织和管理数据的方式。
逻辑存储结构由包含物理文件的表空间组成。逻辑存储结构是oracle外部的组织和管理数据的方式。
逻辑存储结构和物理存储结构对比:
Oracle数据库逻辑上由一个或多个表空间组成,每个表空间在物理上由一个或多个数据文件组成,而每个数据文件是由数据块构成的。所以,逻辑上数据存放在表空间中,而物理上数据存储在表空间所对应的数据文件中。可以用这张图来描述数据文件和表空间的关系。
示例:
本章主要讲解逻辑存储结构。
2.逻辑存储结构简介
逻辑结构类型按照尺寸从小到大分可分为:块(block)–>区(extent)–>段(segment)–>表空间(tablespace)
表空间:数据库是由多个表空间组成的。在创建数据库时会自动创建一些默认的表空间,例如 SYSTEM表空间,SYSAUX表空间等。通过使用表空间,Oracle将所有相关的逻辑结构和对象组合在一起。下面列出常见的表空间,和所存储的信息:
- 数据表空间:用于存储用户数据的普通表空间。
- 系统表空间:默认的表空间,用于保存数据字典(一组保存数据库自身信息的内部系统表和视图,及用于Oracle内部使用的其他一些对象),保存所有的PL/SQL程序的源代码和解析代码,包括存储过程和函数、包、数据库触发器等,保存数据库对象(表、视图、序列)的定义。
- UNDO表空间:用于存放UNDO段,每个实例最多只能使用一个UNDO表空间
- 临时表空间:存储SQL执行过程中产生的临时数据
段:由多个区组成,这些区可以是连续的,也可以是不连续的。当用户在数据库中创建各种具有实际存储结构的对象时(保存有数据的对象),比如表、索引等,Oracle将为这些对象创建“段”。 一般一个对象只拥有一个段。在创建段时,可以为它指定PCTFREE、PCTUSED等参数来控制其中的块的存储空间管理方式,也可以为它指定INITIAL、NEXT、PCTINCREASE等存储参数,以指定其中区的分配方式。如果没有为段指定这些参数,段将自动继承表空间的相应参数。不同类型的数据库对象拥有不同类型的段:
- 数据段:保存表中的记录
- 索引段:索引中的索引条目
- 临时段:在执行查询等操作时,Oracle可能会需要使用到一些临时存储空间,用于临时保存解析过的查询语句以及在排序过程中产生的临时数据。
- UNDO段:保存UNDO数据。
区:由连续的块组成,它是oracle存储空间分配和回收的最小单位。在创建具有独立段结构的数据库对象时,例如表、索引等,Oracle会为数据库对象创建一个数据段,并为数据段分配一个‘初始区’。后续区的分配方式,则根据表的空间管理办法不同,而采用不同的分配方式,例如autoextent,uniform size 或者在创建表或表空间时设置default storage 子句。另外,用户还能够通过执行下面的命令来回收表、索引等对象中未使用的区:
alter table table_name deallocate unused;
块:Oracle用来管理存储的最小单元,也是最小的逻辑存储结构。Oracle数据库在进行输入输出时,都是以块为单位进行读写操作的。建议数据块的尺寸为操作系统块尺寸的整数倍(1、2、4等)。另外,块的大小是在创建数据库的时候决定的,之后不能修改。当然,oracle同时也支持不同的表空间拥有不同的数据块尺寸。
块的头部信息区:
块头:包含块的一般属性信息 如块的物理地址、块所属的段的类型
表目录:如果块中存储的数据是表数据, 则在表目录中保存块中所包含的表的相关信息
行目录:行记录的相关信息 如ROWID
块的存储区:主要包含空闲空间和已经使用的空间。Oracle主要是通过下面的两个参数对这部分空间进行管理的:
(1)PCTFREE参数:指定块中必须保留的最小空闲空间比例。当块中的空闲存储空间减少到PCTFREE所设置的比例后,Oracle将块标记为不可用状态,新的数据行将不能被加入到这个块。
(2)PCTUSED参数:制定一个百分比,当块中已经使用的存储空间降低到这个百分比只下时,这个块才被重新标记为可用状态。
以上两个参数既可以在表空间级别进行设置,也可以在段级别进行设置。段级别的设置优先级更高。
3.段(segment)
在Oracle数据库中,一个数据段(segment)可以供以下方案对象(或方案对象的一部分)容纳数据:
- A table that is not partitioned or clustered
- A partition of a partitioned table
- A cluster of tables
当用户使用 CREATE 语句创建表或簇表时,Oracle创建相应的数据段(data segment)。
表或簇表的存储参数(storage parameter)用来决定对应数据段(data segment)的数据扩展(extent)如何被分配。用户可以使用 CREATE 或 ALTER 语句直接设定这些存储参数。这些参数将会影响与方案对象(object)相关的数据段的存储与访问效率。
Oracle 为物化视图(materialized view)及物化视图日志(materialized view log)创建数据段(data segment)的方式与表或簇表相似。
3.1.段的类型
Table
对于一个只有几百条几千条数据,一个学校的学生成绩表,那么一张表就是一个segments。
Table partition
如果一张表非常大,里面存储了几千万条、上亿条记录,那么对这一张表进行操作,效率就非常低。分区表是将大表的数据分成称为分区的许多小的子集。假如一张表是存放中国13亿人口信息的表,那么这么多条记录是有规律的,可以基于某一个字段将其分开。那么可以根据省级行政区可以划分34个分区,每个分区实际上就是一个独立的表,但在逻辑上这些分区又同属于一张表。
如果一张表是普通的表,只占一个segments;如果一张表是partition的表,可能占多个segments。
Cluster
Oracle中普通的表称为堆表(heap table),堆表中的数据是无序存放的,往往在使用一段时间后,数据就变得非常无序。如下图所示,索引中相同的key对应的数据存放在不同的block中,这时,如果要通过索引查询某个key的数据,就需要访问很多不同的block,代价非常高。
我们发现很多表与表之间的数据有相关性,因为我们访问一个表里的数据,往往要访问另一些表里的数据。我们可以把这些数据物理上存储在一块。
Index
索引是与表和聚集相关的一种选择结构,就当于我们一本书的目录,可以快快速的定位某章某节的页数。索引可以建立在一个表的一列或多列上,那就可以大大提高对表的查询。那么一个index也可能会占一个多个segments 。
Oracle 数据库中每个非分区索引(nonpartitioned index)使用一个索引段(index segment)来容纳其数据。而对于分区索引(partitioned index),每个分区使用一个索引段来容纳其数据。
用户可以使用 CREATE INDEX 语句为索引或索引的分区创建索引段(index segment)。在创建语句中,用户可以设定索引段(index segment)的数据扩展(extent)的存储参数(storage parameter)以及此索引段应存储在哪个表空间(tablespace)中。(表的数据段和与其相关的索引段不一定要存储在同一表空间中。)索引段的存储参数将会影响数据的存储与访问效率。
Index-organized table
索引组织表(IOT),就是存储在一个索引结果中的表。存储在堆中的表是无组织的(也就是说,只要有可用的空间,数据可放在任何地方),IOT中按主键存储和排序。对应用来说,IOT表和一个“常规”表并无差别。使用堆组织表时,必须为表和表主键上的索引分别留出空间。而IOT不存在主键的空间开销,因为索引就是数据,数据就是索引。
IOT带来的好处不仅是节约磁盘空间的占用,更重要的是大幅度降低了I/O,减少了访问缓冲区缓存(尽管从缓冲区缓存获取数据比硬盘要快得多,但缓冲区缓存并不是免费的,也不是廉价的。每个缓冲区缓存获取都需要缓冲区缓存的多个闩,而闩是串行化设备,会限制应用的扩展能力)。
Index partition
相应于table有partition ,那么对一个大的index有也partition 。
分区索引可以分为全局分区索引与本地分区索引,其中本地索引又可以分为本地前缀索引和本地非前缀索引。
本地索引的分区和其对应的表分区数量相等,因此每个表分区都对应着相应的索引分区。使用本地索引,不需要指定分区范围因为索引对于表而言是本地的,当本地索引创建时,Oracle会自动为表中的每个分区创建独立的索引分区。
全局索引以整个表的数据为对象建立索引,索引分区中的索引条目既可能是基于相同的键值但是来自不同的分区,也可能是多个不同键值的组合。 全局索引既允许索引分区的键值和表分区键值相同,也可以不相同。全局索引和表之间没有直接的联系,这一点和本地索引不同。
Undo segment
回滚段用于存放数据修改之前的值(包括数据修改之前的位置和值)。回滚段的头部包含正在使用的该回滚段事务的信息。一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚段可以存放多个事务的回滚信息。
Temporary segment
当Oracle处理一个查询时,经常需要为SQL语句的解析与执行的中间结果(intermediate stage)准备临时空间。Oracle会自动地分配被称为临时段(temporary segment)的磁盘空间。例如,Oracle在进行排序操作时就需要使用临时段。当排序操作可以在内存中执行,或Oracle利用索引执行时,就不必创建临时段。
以下语句的执行过程中可能会使用临时段(temporary segment):
- CREATE INDEX
- SELECT … ORDER BY
- SELECT DISTINCT …
- SELECT … GROUP BY
- SELECT . . . UNION
- SELECT … INTERSECT
- SELECT … MINUS
有些不能使用索引的关联操作(unindexed join),或者需要在子查询间建立相互关系(correlated subqueries),也可能需要使用临时段(temporary segment)。所以当查询包含DISTINCT,GROUP BY,或 ORDER BY 子句时,Oracle有可能使用两个临时段。
Oracle可以为临时表(temporary table)及其索引分配临时段(temporary segment)。临时表中的数据只在会话(session)或事务(transaction)的运行期内存在。
在用户会话(session)期间,如果用户需要,Oracle可以在用户的临时表空间(temporary tablespace)内为用户创建临时段(temporary segment)。管理员可以使用 CREATE USER 或 ALTER USER 语句中的 TEMPORARY TABLESPACE 子句指定用户默认使用的临时表空间。
如果没有为用户指定临时表空间(temporary tablespace),那么默认的临时表空间为 SYSTEM。临时表空间的默认存储参数决定了临时段(temporary segment)的数据扩展(extent)如何分配。在语句结束时Oracle负责移除(drop)临时段。
因为临时段(temporary segment)的分配与回收经常发生,所以有必要为创建临时段准备一个专用的表空间(tablespace)。这样可以分流磁盘设备的I/O,也可以减少由于在 SYSTEM 或其他表空间内频繁创建临时段而造成的碎片。
当 SYSTEM 表空间(tablespace)是本地管理的(locally managed),用户必须在创建数据库的同时定义一个默认的临时表空间(temporary tablespace)。本地管理的 SYSTEM 不能用于默认的临时表空间。
因为排序等操作引起的临时段(temporary segment)内的数据变化并不记录到重做日志(redo log)中,只有对临时段进行空间管理的操作才被记录。
LOB segment
Large object (LOB) 大对象,我们知道数据库不但可以存数据,有些可以存储视频声音图片等文件,这种类型文件的大小几MB,几十MB很正常。当然,有些数据库是不支持LOB数据类型的,可以在表里存一个指针,来指向某个文件下的视频声音文件。
Nested table
嵌套表,就是在表里存一个指针,指针指向另外一张表。
Bootstrap segment
初始引导程序<初始化实例>
3.2.ASSM和MSSM
段空间有两种管理方式:
- 自动段空间管理(Auto Segment Space Management,ASSM),它首次出现在Oracle 9.2中。自由列表FREELIST被位图所取代,它是一个二进制的数组,能够迅速有效地管理存储扩展和剩余区块(Free Block),因此能够改善分段存储本质。ASSM会忽略PCTUSED参数而只使用PCTFREE参数。”SEGMENT SPACE MANAGEMENT AUTO” 不需要指定, 是默认设置。
ASSM表空间上创建的段还有另外一个称呼叫Bitmap Managed Segments(BMB段) -
手动段空间管理(Manual Segment Space Management,MSSM),可以设置FREELIST、PCTUSED和PCTFREE等参数来控制如何分配和使用段中的空间。
查看段空间管理方式:
select tablespace_name, segment_space_management from user_tablespaces;
TABLESPACE_NAME SEGMEN
------------------------------ ------
SYSTEM MANUAL
SYSAUX AUTO
UNDOTBS1 MANUAL
TEMP MANUAL
USERS AUTO
create tablespace peacock
datafile '/oradata/data/peacock01.dbf'
size 10m
EXTENT MANAGEMENT LOCAL -- Turn on LMT
SEGMENT SPACE MANAGEMENT AUTO -- Turn on ASSM;
一旦定义好了tablespace,表和索引就能够使用各种方法很容易地被添加到新的tablespace里,带有ASSM的本地管理tablespace会略掉任何为PCTUSED、NEXT和FREELISTS所指定的值。
当表格或者索引被分配到这个tablespace,表格或者索引的PCTUSED的值会被忽略,而Oracle9i会使用位图数组来自动地管理tablespace里表格和索引的空闲数据块。对于在LMT的tablespace内部创建的表格和索引而言,这个NEXT扩展子句是过时的,因为由本地管理的tablespace会管理它们。但是,INITIAL参数仍然是需要的,因为Oracle不可能提前知道初始表格加载的大小。对于ASSM而言,INITIAL最小的值是三个块。
使用ASSM的一个巨大优势是,位图freelist能够减轻缓冲区忙等待(buffer busy wait),这个问题在Oracle9i以前的版本里曾是一个严重的问题。
在没有多个freelist的时候,每个Oracle表格和索引在表格的头部都曾有一个数据块,用来管理对象所使用的剩余区块,并为任何SQL插入声明所创建的新数据行提供数据块。当数据缓冲内的数据块由于被另一个DML事务处理锁定而无法使用的时候,缓冲区忙等待就会发生。当需要将多个任务插入到同一个表格里的时候,这些任务就被强制等待,而同时Oracle会在同时分派剩余的区块,一次一个。
有了ASSM之后,Oracle宣称显著地提高了DML并发操作的性能,因为(同一个)位图的不同部分可以被同时使用,这样就消除了寻找剩余空间的串行化。根据Oracle的测试结果,使用位图freelist会消除所有分段头部(对资源)的争夺,还能获得超快的并发插入操作
3.3.FREELIST(自由列表)
Oracle通过维护FREELIST来记录或更新所有可用的数据块。
当执行INSERT语句时,Oracle首先在FREELIST列表上搜索可用的空闲数据块,搜索成功之后将数据插入到那个空闲块。块在FREELIST列表中的可用性由PCTFREE参数值来决定。起初一个空块在FREELIST列表上列出,并且会一直保留,直到空闲空间达到PCTFREE设定的值。当一个块被使用且达到PCTFREE设定的值之后,该块将从FREELIST列表被移除,而当数据块的可用空间低于PCTUSED值的时候,该块又会回收,即重新回到FREELIST列表。Oracle使用FREELIST方式以提高数据库性能。因此,每一个INSERT操作,Oracle仅仅需要搜索FREELIST结构,而不是搜索所有数据块。从Oracle 9i开始,引入了ASSM,它让Oracle自动管理FREELIST。在ASSM里,Oracle使用位图方式来标记数据块是否可用,这种数据块的空间管理方式比用一个列表来管理效率更高。
3.4.段空间管理
数据库在INSERT,UPDATE操作时都需要请求空闲的数据块,由于不可能每次操作时都去每个数据块查询一下看看有没有空闲的块(如果这样那效率太低了)。为了解决这个问题,ORACLE的在每个段的段头有一个空闲数据块指针链表的结构,这个就称为FREELISTS,FREELISTS列表代表链表的长度。表面上看像解决了问题,但在高并发对一个表的插入或更新时,一个空闲链表往往会出现等待的现象,所以为了提高性能,又增加了多个空闲链表的处理,也就是FREELIST-GROUPS,也就说段有多少个空闲链表是FREELIST-GROUPS参数决定。
在ORACLE9.2以前,对于一些高并发的表需要检查FREELISTS和FREELIST-GROUPS参数是否满足应用的要求。从ORACLE9.2新增加了ASSM(表空间段自动管理)的新特性,有了ASSM,链接列表FREELISTS被位图结构所取代,所以也根本不需要指定什么FREELISTS和FREELIST-GROUPS参数了,一个段里哪些数据块是空闲的,那些是可以再使用的,在这个位图里全部可以取到,并且全部是由ORACLE自动管理。
通过测试与实践,采用自动段管理的表,在并发处理性能上表现非常好,所以基本上现在的表都采用段自动管理了,因此FREELISTS和FREELIST-GROUPS参数也就成为过去。
create tablespace test1
datafile '/db/oracle/oradata/TESTDB/test1.dbf' size 10M
autoextend on next 1M
maxsize 1G
extent management local uniform size 6M
segment space management auto;
segment space management auto
The segment_management_clause is relevant only for permanent, locally managed tablespaces.
Specify AUTO if you want the database to manage the free space of segments in the tablespace using a bitmap. If you specify AUTO, then the database ignores any specification for PCTUSED, FREELIST, and FREELIST GROUPS in subsequent storage specifications for objects in this tablespace. This setting is called automatic segment-space management and is the default.
Specify MANUAL if you want the database to manage the free space of segments in the tablespace using free lists. Oracle strongly recommends that you do not use this setting and that you create tablespaces with automatic segment-space management.
If you specify AUTO segment management, then:
If you set extent management to LOCAL UNIFORM, then you must ensure that each extent contains at least 5 database blocks.
If you set extent management to LOCAL AUTOALLOCATE, and if the database block size is 16K or greater, then Oracle manages segment space by creating extents with a minimum size of 5 blocks rounded up to 64K
segment space management子句仅适用于永久的本地管理的表空间。
如果希望数据库使用位图管理表空间中的段的可用空间,请指定AUTO。 如果指定AUTO,则数据库将在此表空间中的对象的后续存储中忽略指定的PCTUSED,FREELIST和FREELIST GROUPS。 此设置称为自动段空间管理,是默认设置。
如果希望数据库使用FREELIST管理表空间中的段的可用空间,请指定MANUAL。 Oracle强烈建议您不要使用此设置。
如果指定AUTO段管理,则:
如果将Extent管理设置为LOCAL UNIFORM,则必须确保每个Extent至少包含5个数据库Block。
如果将Extent管理设置为LOCAL AUTOALLOCATE,并且如果数据库Block大小为16K或更大,则Oracle将通过创建最小为5个Block(???),最大为64K的Extent数据块来管理Extent空间。
4.区(extent)
Extent是由一组连续的数据块(data block)构成的数据库逻辑存储分配单位。而段(segment)则是由一个或多个Extent构成。当一个段中已有空间已经用完,Oracle为这个段分配新的Extent。
4.1.Extent分配
当用户创建数据表时,Oracle为此表的数据段(data segment)分配一个包含若干数据块(data block)的初始数据扩展(initial extent)。虽然此时数据表中还没有数据,但是在此初始Extent中的Block已经为插入新数据做好了准备。
如果一个段(segment)的初始数据扩展(initial extent)中的数据块(data block)都已装满,且有新数据插入需要空间时,Oracle自动为这个segment分配一个增量数据扩展(incremental extent)。Incremental extent是一个segment中继已有Extent之后分配的后续Extent,它的容量大于或等于之前的Extent。
为了管理的需要,每个segment的段头(header block)中包含一个记录此segment所有extent的目录。
本章的内容适用于串行执行(serial operation)的情况,即只有一个服务进程解析、执行 SQL 语句。对于并行执行(parallel)的 SQL 语句(即一个语句由多个服务进程执行),数据扩展(extent)的分配情况有所不同。
INITIAL和MINEXTENTS参数
CREATE TABLE test(a number)
STORAGE(
INITIAL 100K
NEXT 100K
MINEXTENTS 2
MAXEXTENTS 100
PCTINCREASE 100);
一旦建立了表对象,它的INITIAL和MINEXTENTS参数不能被修改。对于NEXT和PCTINCREASE的任何修改都只影响后来分配的Extent。在分配一个新Extent时,系统直接按NEXT的值分配一个Extent,然后用公式:前一NEXT值*(1+(PCTINCREASE/100)) 计算出下一个应该分配的Extent的大小,并把计算结果保存到相关数据字典的NEXT_EXTENT列上,做为下一个应该分配的Extent的大小。
解释:
初始给test表分配两个Extent,
第一个Extent是100K,因INITIAL=100K
第二个Extent是100K,因NEXT=100K
如果因表内数据增长,需要分配第三个Extent,因PCTINCREASE是100,则
第三个Extent是200K=100K+100K
第四个Extent是400K=200K+200K
可通过数据字典表DBA_TABLES、ALL_TABLES、USER_TABLES查看参数设置情况,如:
select table_name,initial_extent,next_extent,min_extents,max_extents,pct_increase from user_tables;
如何决定Extent的数量与容量
每个段(segment)的定义中都包含了extent的存储参数(storage parameter)。存储参数适用于各种类型的段。这个参数控制着Oracle如何为段分配可用空间。例如,用户可以在 CREATE TABLE 语句中使用 STORAGE 子句设定存储参数,决定创建表时为其数据段(data segment)分配多少初始空间,或限定一个表最多可以包含多少Extent。如果用户没有为表设定存储参数,那么表在创建时使用所在表空间(tablespace)的默认存储参数。
用户既可以使用数据字典管理的表空间(dictionary managed tablespace)(依赖数据字典表监控空间的利用情况),也可以使用本地管理的表空间(locally managed tablespace)(使用位图(bitmap)来标记可用与已用空间)。由于本地管理的表空间性能较好且易于管理,当用户没有显式地设定extent管理参数时,除了 SYSTEM 之外的所有永久表空间(permanent tablespace)默认使用本地管理方式。
在一个本地管理的表空间中,其中所分配的extent的容量既可以是用户设定的固定值,也可以是由系统自动决定的可变值。当用户创建表空间(tablespace)时可以使用 UNIFORM (用户指定)或 AUTOALLOCATE (由系统管理)子句设定数据扩展的分配方式。
- 对于固定容量(UNIFORM)的extent,用户可以为extent设定容量或使用默认大小(1 MB)。用户须确保每个extent的容量至少能包含5个数据块(database block)。本地管理(locally managed)的临时表空间(temporary tablespace)在分配extent时只能使用此种方式。
- 对于由系统管理(AUTOALLOCATE)的extent,由Oracle决定新增extent的最佳容量,其最小容量为 64 KB。如果创建表空间时使用了“segment space management auto”子句,且数据块容量大于等于 16 KB,Oracle扩展一个段时(segment)所创建的extent的最小容量为 1 MB。对于永久表空间(permanent tablespace)上述参数均为默认值。
在本地管理的表空间(locally managed tablespace)中,INITIAL,NEXT,PCTINCREASE,和 MINEXTENTS 这四个存储参数可以作用于段(segment),但不能作用于表空间。INITIAL,NEXT,PCTINCREASE,和 MINEXTENTS 相结合可以用于计算段的初始容量。当段容量确定后,Oracle使用内部算法确定其中每个初始extent的容量。
数据扩展如何被分配
Oracle依据表空间管理方式的不同(本地管理(locally managed)或数据字典管理(dictionary managed)),选择不同的算法分配extent。
对于本地管理的表空间(locally managed tablespace),Oracle在为新的extent寻找可用空间时,首先选择一个属于此表空间的数据文件(datafile),再搜索此数据文件的位图(bitmap)查找连续的数据块(free block)。如果此数据块中没有足够的连续可用空间,Oracle将查询其它数据文件。
提示:
Oracle 强烈建议用户使用本地管理的表空间(locally managed tablespace)。
CREATE TABLESPACE TS_EXAMPLE
NOLOGGING
DATAFILE '/oradata/data/ts_example01.dbf' SIZE 2048M,
AUTOEXTEND ON NEXT 100M MAXSIZE 20480M
EXTENT MANAGEMENT LOCAL;
4.2.Extent分配示例
- 建初始表
create table t5 as select * from user_tables;
- 查看段的初始extent分配
select segment_name, extent_id, bytes from user_extents where segment_name='T5';
SEGMENT_NA EXTENT_ID BYTES
---------- ---------- ----------
T5 0 65536
T5 1 65536
T5 2 65536
T5 3 65536
T5 4 65536
T5 5 65536
T5 6 65536
T5 7 65536
T5 8 65536
- 向表段中插入数据,使Oracle为该段分配更多的extent
insert into t5 select * from user_tables;
select segment_name, extent_id, bytes from user_extents where segment_name='T5';
SEGMENT_NA EXTENT_ID BYTES
---------- ---------- ----------
T5 0 65536
T5 1 65536
T5 2 65536
T5 3 65536
T5 4 65536
T5 5 65536
T5 6 65536
T5 7 65536
T5 8 65536
T5 9 65536
T5 10 65536
T5 11 65536
T5 12 65536
T5 13 65536
T5 14 65536
T5 15 65536
T5 16 1048576
17 rows selected.
- 回收T5段的extent
SQL> delete t5;
2981 rows deleted.
select segment_name, extent_id, bytes from user_extents where segment_name='T5';
SEGMENT_NA EXTENT_ID BYTES
---------- ---------- ----------
T5 0 65536
T5 1 65536
T5 2 65536
T5 3 65536
T5 4 65536
T5 5 65536
T5 6 65536
T5 7 65536
T5 8 65536
T5 9 65536
T5 10 65536
T5 11 65536
T5 12 65536
T5 13 65536
T5 14 65536
T5 15 65536
T5 16 1048576
此时表段的数据已经删除,但所有extent依然存在;
truncate table t5;
select segment_name, extent_id, bytes from user_extents where segment_name='T5';
SEGMENT_NA EXTENT_ID BYTES
---------- ---------- ----------
T5 0 65536
truncate表后,表的exten空间被回收。
4.3.Extent回收
Oracle 数据库提供了 Segment Advisor 工具,依据方案对象(schema object)存储空间中的碎片程度来判断此对象中是否包含可回收的空间。
一般来说,在用户将一个段(segment)对应的方案对象(schema object)移除(使用 DROP TABLE 或 DROP CLUSTER 语句)之前,此段的extent不会被回收到表空间(tablespace)中,但是以下情况例外:
- 表,簇表的所有者(owner)或拥有 DELETE ANY 权限的用户, 可以使用 TRUNCATE…DROP STORAGE 语句将表,簇表的数据清除
- DBA 可以使用以下语法收回一个段中未使用的extent:
ALTER TABLE table_name DEALLOCATE UNUSED; - 如果用户为回滚段(rollback segment)设定了 OPTIMAL 参数,Oracle将周期性地从其中回收extent。
当extent被释放后,Oracle修改数据文件(datafile)中的位图(bitmap)(对于本地管理的表空间)或更新数据字典(对于数据字典管理的表空间),将回收的extent视为可用空间。被释放的extent中的数据无法继续访问。
4.3.1.Extents in Nonclustered Tables
只要用户没有移除(drop)或清空(truncate)非簇表(nonclustered table),那么对应数据段(data segment)内的任何数据块(data block)都不会被回收。Oracle会在插入数据时使用这些数据块(只要数据块有足够的空间)。即使用户删除(delete)了表的所有行,Oracle也不会回收此表的block供表空间内的其他方案对象(schema object)使用。
当用户移除(drop)了一个非簇表(nonclustered table),Oracle将在需要空间时回收此表对应的extent。Oracle将此表对应的数据段(data segment)、索引段(index segment)中包含的extent全部收回,并供存储于此表空间(tablespace)的其他方案对象(chema object)使用。
对于数据字典管理的表空间(dictionary managed tablespace),当一个段(segment)需要的extent比现有可用扩展的都大时,Oracle通过寻找、合并连续的被回收的extent来形成更大的extent。这个过程被称为extent合并(coalescing)。本地管理的表空间(locally managed tablespace)没有必要进行extent合并,因为所有连续空间都可以被用于分配新extent,而无需关心所用空间是如何被回收的。
4.3.2.Extents in Clustered Tables
簇表(clustered table)的数据存储在为整个簇(cluster)分配的数据段(data segment)中。因此当用户移除(drop)簇中的一个表时,数据段还要为簇中的其它表保留,因此没有extent被回收。用户可以通过清空(truncate)整个簇来回收属于簇的extent(哈希簇(hash cluster)除外)。
4.3.3.Extents in Materialized Views and Their Logs
Oracle回收属于物化视图(materialized view)及其日志(materialized view log)的extent的方式与表或簇相同。
4.3.4.Extents in Indexes
只要索引存在,那么对应索引段(index segment)的所有extent都不会被回收。当用户移除(drop)索引或相关的表、簇表时,Oracle才将索引使用的extent回收。
4.3.5.Extents in Temporary Segments
当Oracle执行完一个 SQL 语句,且在执行过程中使用的临时段(temporary segment)时,Oracle自动地移除(drop)临时段,并将属于此临时段的extent空间还给临时段所在的表空间(tablespace)。当用户执行单一排序(single sort)语句时,Oracle将在此用户的临时表空间(temporary tablespace)中创建为这个排序服务的临时段(temporary segment),并在执行后将此临时段使用的extent回收。
但是对于多重排序(multiple sort),可能会使用临时表空间(temporary tablespace)中专为排序而创建的排序段(sort segment)。在每个实例中只会分配一个排序段,在排序操作使用后也不会被回收,而是继续供以后的多重排序使用。
同一会话或同一事务的多个 SQL 语句,有可能共同使用一个临时表(temporary table)的临时段(temporary segment)存储临时数据。在这种情况下,Oracle在会话或事务结束后 才移除(drop)临时段,并为临时段所在表空间回收使用的extent。
4.3.6.Extents in Rollback Segments
Oracle周期性地检查数据库回滚段(rollback segment)的容量是否超过了最优值(optimal size)。如果回滚段超过了这个最优值(即回滚段中的extent过多),Oracle将自动地从回滚段回收一些extent。
5.块(block)
转载自:http://blog.itpub.net/26736162/viewspace-2141499/
作者:lhrbest
5.1.简介
操作系统块是操作系统读写的最小操作单元,也是操作系统文件的属性之一。当创建一个Oracle数据库时,选择一个基于操作系统块的整数倍大小作为Oracle数据库块的大小。Oracle数据库读写操作则是以Oracle块为最小单位,而非操作系统块。
Oracle块对应磁盘上一个或多个物理块,它的大小由初始化参数DB_BLOCK_SIZE决定,可以定义数据块为2K、4K、8K、16K、32K甚至更大,默认Oracle块大小是8K。若一旦设置了Oracle数据块的大小,则在整个数据库生命期间不能被更改。使用一个合适的Oracle块大小对于数据库的调优是非常重要的。
Oracle就是通过数据块来屏蔽不同操作系统存储结构的差异的。无论是Windows环境,还是Unix/Linux环境,它们的存储结构和方式、甚至字符排列的方式都是不同的。Oracle利用数据块将这些差异加以屏蔽,全部数据操作采用对Oracle块的操作,相当于是一个层次的抽象。
Oracle所有对数据的操作和空间分配,实际上都是针对Oracle块的操作。从数据表中搜索出一行,实际上Oracle会从内存缓冲区(或者硬盘)中读取到该行所在的数据块,再返回这数据块上的指定数据行。Oracle无论是在缓冲区,还是在硬盘,进行数据操作的最小单位是数据块。
服务器进程读取相应的 Oracle 块时,会调用 Oracle I/O 引擎,然后 Oracle I/O 引擎向操作系统发出请求,操作系统在通过内核进行相应的系统调用接口读取操作系统块;然后文件系统调用相应的块设备进行扇区数据读写。
查看块的大小:
SQL> show parameter db_block_size;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_block_size integer 8192
数据块的大小应依据不同类型的操作系统设置。如果数据块设置比较大,那么一次读取的数据行较多,对SGA内存消耗较大,特定查询引发的换入换出可能较多。如果设置的过小,频繁的IO逻辑物理读也会引起性能问题。
与数据块有关的另一个参数是db_file_multiblock_read_count,表示一次从物理存储中读取的数据块数量。对一些数据挖掘系统,可以考虑调节此参数略大一些。
SQL> show parameter db_file_multiblock_read_count
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_file_multiblock_read_count integer 82
OS在每次执行I/O的时候是以OS的块为单位;Oracle在每次执行I/O的时候是以Oracle块为单位。Oracle块具有以下特点:
① 最小的I/O单元;
② 包含一个或多个OS块;
③ 大小由参数DB_BLOCK_SIZE决定;
④ 数据库创建时设置,数据库创建后不能更改。
5.2.块结构
在Oracle中,不论数据块中存储的是表(TABLE)、索引(INDEX)或簇表(CLUSTER TABLE),其内部结构都是类似的。Oracle块的结构如下图所示:
一个Oracle块大约由数据块头(包括标准内容和可变内容,Common And Variable Header)、表目录(Table Directory)、行目录(Row Directory)、可用空间(Free Space)和行数据(Row Data)这几部分组成。图中两个箭头表示一个数据块中的可用空间区的容量是可变的。
●数据块头(Block Header):主要包含有数据块地址的一些基本信息(块地址,Block Address)和段的类型(表段、索引段等)。块头自上而下进行增长。
●表目录(Table Directory):如果一个堆组织表在此数据块中储存了数据行,那么该表的信息将被记录在数据块的表目录中。多个表可以将行存储在相同的块中。
●行目录(Row Directory):此区域包含数据块中存储的数据行的信息,即每个数据行片断(Row Piece)在行数据(Row Data)中的地址。一个数据块中可能保存一个完整的数据行,也可能只保存数据行的一部分。当一个数据块(Data Block)的行目录(Row Directory)空间被使用后,即使数据行被删除(DELETE),行目录空间也不会被回收。举例来说,当一个曾经包含50条记录的数据块被清空后,其块头(Header)的行目录仍然占用100字节(Byte)的空间。仅在块中插入新行时,数据库才会重用此空间。
●可用空间(Free Space):是指可以为以后的更新和插入操作分配的空间,大小由PCTFREE和PCTUSED两个参数影响。可用空间位于块的中部,允许头和行数据空间在必要时进行增长。当插入新行或用更大的值更新现有行的列时,行数据会占用可用空间。导致块头增长的事件包括:行目录需要更多的行条目和需要的事务处理插槽数多于最初配置的数目。块中的可用空间最初是相邻的。但是,删除和更新操作可能会使块中的可用空间变成碎片。
●行数据(Row Data):数据块(Data Block)中行数据(Row Data)包含了表或索引的实际数据。一个数据行可以跨多个数据块。行数据空间自下而上进行增长。
数据块头(data block header),表目录区(table directory),行目录区(rowdirectory)被统称为管理开销(overhead)。这部分不存数据库中实际的数据,而是用来记录该块的逻辑结构,而且这部分占用的空间不是固定的,大约在84-107字节之间。
5.3.概念
5.3.1.PCTFREE(空闲率)和PCTUSED(使用率)
PCTFREE和PCTUSED这两个参数用来优化数据块空间的使用,控制数据块是否出现在FREELIST中。当创建或者更改任何表和索引的时候,Oracle使用这两个参数管理块空间的使用。
●PCTFREE:参数定义了一个块保留空间的百分比,保留空间是为了将来可能发生的更新操作,因为更新可能增大被更新行占用的空间,如果此时该块没有可利用空间,那么只有发生row migrate了,从而会降低I/O性能。换句话说,就是当一个块的利用率达到(1 – PCTFREE / 100)的时候,oracle就将该块从FREELIST中移除,不再向该块插入数据。所以说PCTFREE是控制什么时候将块从FREELIST中移除的。
对于表和索引来说,该值默认为10%,通过查询DBA_TABLES或DBA_INDEXES视图的PCT_FREE列可以获取到PCTFREE的值。该值适用于MSSM和ASSM。
●PCTUSED:参数控制一个块什么时候被重新启用来插入数据,例如当一个块达到1-pctfree利用率的时候,oracle停止向该块插入数据,同时从FREELIST移除该块,但是后来发生一些删除操作,使得该块的利用率下降,当该块的利用率降到PCTUSEDd以下的时候该块就被重新启用来插入数据了,也即是将该块重新加入到FREELIST列表中,所以说PCTUSED是控制什么时候将一个块重新加入FREELIST的。
举个例子:比如一个块的PCTFREE定为10%,PCT_USED定为40%(oracle默认设置)。那么一个块的使用率达到90%(100 – PCTFREE / 100 = 90%)的时候,oracle将该块从FREELIST中移除,停止使用该块来插入数据(但可更新)。后来该块上发生了一些删除操作,使得该块的利用率下降,当使用率下降到40%以下的时候,oracle重新将该块加入FREELIST,可用于新的插入。
通过查询DBA_TABLES视图的PCT_USED列可以获取到PCTFREE的值。该值仅适用于MSSM。
PCTFREE和PCTUSED的值可以在创建表时指定,也可以在创建表后用修改,但是要注意的是,修改后的值,只对修改后的数据操作有影响,对之前的无效。因为OLTP系统对数据块的DML操作会较为频繁,所以在OLTP系统中正确配置这两个属性可能会对性能有一定的提高。
在Oracle11g中,表空间默认使用本地位图自动管理,PCTFREE的默认值是10,且无法自定义管理PCTUSED属性,除非将表空间设置为手动管理。
下面是一个比较形象的比喻,大家可以参考:
把BLOCK 想成一个水杯。侍者把水倒入放在我们面前的水杯,要多满呢,我们要求他倒 9 分满好了,这时 PCTFREE 代表着设定为 10 ,意思就是说,当 BLOCK 使用到达 90% 的时候,就不可以再使用了,这个 BLOCK 应该从 FREELIST 列表中移除 (un-link) 。为何要保留 10% 的空间呢?这是为了提供 update 资料时所可能增加的空间使用,如果空间保留得太小,就容易发生 row chaining 。
PCTUSED 代表着这杯水什么时候可以添加,假设 PCTUSED 为 40 ,代表当我们把水杯的水喝到剩下 40% 以下时,侍者就会知道需要加水了。你想想看,如果说在餐厅里你每喝一口水侍者就来加水,你会不会觉得很烦,对餐厅来说,也要派很多人不断帮每桌客人加水,这生意还能做吗?所以说, PCTUSED 代表着 re-link 回 FREELIST 的意义,如果说 PCTUSED 设得太大,例如 70 好了,代表这杯水你随便喝一口,侍者就要来加水了,这隐含的意义是,这个杯子的利用率增加,但是侍者頻繁的服务造成了负荷 (I/O Overhead) 。 PCTUSED 设小一点,例如 10 ,代表当水喝到剩下 10% 的時候 ( 如同 DELETE 事务操作 ) ,才需要放回 FREELIST ,代表可以加水了 ( 如同 INSERT 事务操作 ) 。
简单地说,如果希望存储空间发挥最大使用效益,可以把PCTUSED设大一点,相反的,如果想要提高IO效能,应该把PCTUSED设定小一点。
通过user_tables的pct_free,pct_used来查看PCTFREE和PCTUSED的值:
select table_name, pct_free, pct_used from user_tables;
TABLE_NAME PCT_FREE PCT_USED
------------------------- ---------- ----------
SEG0 0
UET 0 0
USER0 0
TSQ 0 0
UNDO10 40
FILE 10 40
OBJ$ 10 40
说明:
pctfree表示用于保留更新操作的百分比,如果超过该值不能插入数据。
pctused表示数据所占最低百分比,如果达到pctfree时不能插入,delete后如果达到pctused才可以insert。
可以使用ALTER语句修改表的PCTFREE和PCTUSED的值。修改之后只对新块起作用,若要对表中原有的块起作用,则可以使用MOVE重组表,例如:
ALTER TABLE TABLE_NAME PCTFREE 20;
ALTER TABLE TABLE_NAME MOVE;
修改索引的PCTFREE的值:
ALTER INDEX PK_TABLE_NAME REBUILD PCTFREE 20;
5.3.2.空闲空间的使用
Insert这时候块的自由空间会减少,Update的时候块的自由空间也会可能会改变。
DELETE语句删除块中的记录或者使用UPDATE语句把列的值更改成一个更小值的时候,Oracle会释放出一部分自由空间。释放出的自由空间并不一定是连续的,常情况下,Oracle不会对块中不连续的自由空间进行合并。因为合并数据块中不连续的自由空间会影响数据库的性能。只有当用户进行数据插入(INSERT)或者更新(UPDATE)操作,却找不到连续的自由空间的时候,Oracle才会合并数据块中不连续的自由空间。
5.3.3.行链接(Row Chaining)
数据库中INSERT一行数据,如果行数据很大,以至于一个数据块存不下一整行,Oracle就会把一行数据分作几段存在几个数据块中,这个过程叫行链接(Row Chaining)。
普通行是指这行数据能够存放在一个数据块中;链接行是指这行数据存放在多个数据块中。
5.3.4.行迁移(row migration)
数据块中存在一条记录,用户执行UPDATE更新这条记录,这个UPDATE操作使这条记录变长,这时候,Oracle在这个数据块中进行查找,但是找不到能够容纳下这条记录的空间,Oracle只能把整行数据移到一个新的数据块。原来的数据块中保留一个“指针”,这个“指针”指向新的数据块。被移动的这条记录的ROWID保持不变。
5.3.5.INITRANS和MAXTRANS
INITRANS设置块首部中事务表的初始大小。该值影响着对表的事务的并发访问(表默认是1,索引默认是2)。事务表会根据需要动态扩展,最大达到MAXTRANS个条目(假设块上有足够的自由空间)。所分配的每个事务条目需要占用块首部中的23~24字节的存储空间。Oracle 10g以后MAXTRANS 被忽略,所有的MAXTRANS 都是255。
如果某个事务锁定了这个块的数据,则会在事务条目中记录事务的标识,这个事务首先查看这个事务条目是否已被占用,如果是,则去查看占用的事务是否为活动状态。如果不是活动状态,比如已经提交或者回滚,则可以覆盖这个事务条目。如果是活动状态,则需要等待闩被释放,如果有大量的并发访问使用的这个块,则MAXTRANS参数不能设置太小,否则资源竞争将导致系统并发性能下降。
ORACLE 事务并发的块的分配和ITL管理:
1. INITRANS =1 时,并发多个INSERT 事务的时候,并不会由于ITL的争用而等待产生,ORACLE 采取的策略是每个INSERT事物分配不同的一些块来使用,这样各个会话之间就不会产生冲突,除非段没有多余的块。
2. INITRANS=1 时,并发多个UPDATE事务的时候,并不会由于ITL的争用而导致等待产生,此时ORACLE除了使用默认的ITL之外,另外动态扩展所需要的ITL,仅在非常极端的情况下才会出现等待,例如:
1) 该BLOCK没有FREE空间了,PCTFREE参数不可以设置太小。
2) 该块使用的ITL总数,超过该块允许的ITL的最大值min(round(block_size*0.5/24) – 2 ,255) 。
在实际的生产环境中要达到这样的极端情况是很难的,应该比应用SQL的死锁出现的概率更小。
创建表的时候除非已经清楚,大部分的情况下没有必要调整INITRANS参数,通常1-4以下足够用了,INITRANS 设置非常大的时候ORACLE 有出现坏块的BUG,另外不要随意改小PCTFREE参数,除非已经很清楚更改的结果。
5.4.示例
SQL> create table sales_info (customer_name varchar(20), total number);
Table created.
SQL> CREATE INDEX idx_sales_info ON sales_info(customer_name);
Index created.
SELECT T.PCT_FREE, T.PCT_USED, T.INI_TRANS FROM DBA_TABLES T
WHERE T.TABLE_NAME ='SALES_INFO';
PCT_FREE PCT_USED INI_TRANS
---------- ---------- ----------
10 40 1
SELECT T.index_name, T.table_name, T.pct_free, T.ini_trans FROM DBA_INDEXES T
WHERE T.TABLE_NAME ='SALES_INFO';
INDEX_NAME TABLE_NAME PCT_FREE INI_TRANS
-------------------- -------------------- ---------- ----------
IDX_SALES_INFO SALES_INFO 10 2
--修改表的PTCFREE和PCTUSED的值
ALTER TABLE SALES_INFO PCTFREE 20 PCTUSED 60;
--表重组
ALTER TABLE SALES_INFO MOVE;
--修改索引的PTCFREE值
ALTER INDEX IDX_SALES_INFO REBUILD PCTFREE 20;
5.5读取和修改数据块的过程
Hash Latches、HashBucket 、buffer Header及Buffer cache之间的关系图:
5.5.1.读操作
非唯一索引方式,非索引根块和分支块
- 对要访问的块地址做HASH
HASH(FILE#,BLOCK#) = hash_value(HV)
- 根据HV找到对应的HASH bucket
-
以独占方式申请管辖此bucket的CBC latch
-
搜索bucket中的hash_chain,比对hash_chain上的buffer_header,找到目标buffer_header
-
修改buffer_header中的buffer pin锁为S(share)模式(之前为0,无锁)
-
释放CBC latch.
-
根据buffer_header中的buffer_address指针找到buffer
-
读取buffer中的数据到PGA中.
-
以独占方式申请管辖此bucket的CBC latch
10.修改BH中的buffer pin锁为0(无锁)模式
11.释放CBC latch
5.5.2.读操作
唯一索引方式所有块,非唯一索引根块和分支块
- 对要访问的块地址做HASH
HASH(FILE#,BLOCK#) = hash_value(HV)
- 根据HV找到对应的HASH bucket
-
以共享方式申请管辖此bucket的CBC latch
-
搜索bucket中的hash_chain, 比对hash_chain上的buffer_header,找到目标buffer_header
-
根据buffer_header中的BA指针找到buffer
-
读取buffer中的数据到PGA中
-
释放CBC latch
5.5.3.写操作
- 对要访问的块地址做HASH
HASH(FILE#,BLOCK#) = hash_value(HV)
-
根据HV找到对应的HASH bucket
-
以独占方式申请管辖此bucket的CBC latch
-
搜索bucket中的hash_chain,比对hash_chain上的buffer_header,找到目标buffer_header
-
修改buffer_header中的buffer pin锁为X(exclusive)模式(之前为0,无锁)
-
释放CBC latch
-
根据buffer_header中的buffer_address指针找到buffer
-
产生redo数据
-
修改buffer中的数据.
-
以独占方式申请管辖此bucket的CBC latch.
10.修改buffer_header中的buffer pin锁为0模式
11.释放CBC latch
5.5.4.逻辑读
- 找到buffer_header后,读取buffer_header中的buffer_address
-
根据buffer_address访问buffer_cache中的目标buffer
5.5.5.物理读
-
搜遍hash_chain上的BH都没有找到目标buffer_header
-
从数据文件中加载block到buffer中
-
并将buffer头链入对应的BUCKET中的hash_chain上
-
访问buffer
5.5.6.latch和pin
buffer_cache中的buffer对每个server_process都是公有资源谁都可以读,谁都可以改,为保证这些链不被并发修改导致破坏。oracle采用latch和buffer_pin锁来控制对内存结构体使用时的并发。
latch
某个服务器进程在hash_chain上搜索buffer_header时,另一个进程要做入链出链的操作,对于一个buffer, 两个进程同时都要去做出入链,内存没有安全保证。
oracle对hash_chain必须加以保护。 oracle采取的保护方式就是latch(闩锁),确切的说是:cache buffer chain latch,简称为: CBC latch。
例如:进程A在搜索链表上的buffer_header时, 进程B不可以更改hash_chain;进程A在更改hash_chain时, 进程B不可以搜索hash_chain。
pin
当在hash_chain上找到目标buffer_header时, 根据访问方式要对buffer_header加锁。才能根据buffer_address访问buffer。这把上在buffer_header上的锁称之为buffer pin。
5.5.7.共享与独占
无论是CBC latch还是buffer pin都有锁的保持模式。他们都有共享和独占模式,对公有资源而言,有独占就有争用。
CBC latch共享:
1. 读非唯一索引的根块+分支块。读非唯一索引的叶子块是独占模式。
2. 通过唯一索引访问时, 索引的根块+分支块+叶子块+表块
原因:因为根块和分支块的访问频度高,而且很少改动。
因此,建索引尽量建唯一索引,INDEX UNIQUE SCAN (共享latch),INDEX RANGE SCAN(独占latch)。
CBC latch独占:
1. 所有涉及改的操作。
2. 以及上面列出的共享持有以外的所有读操作。
获取CBC latch的目的是:
1. 在hash chain上的双向链表搜索buffer_header
2. 在buffer_header中修改buffer pin锁的状态
buffer pin何时共享持有:通过buffer_heade中的Buffer Address读buffer
buffer pin何时独占持有:通过buffer_heade中的Buffer Address写buffer
buffer pin何时无需持有:
1. 所有不涉及索引的根块+分支块改动的读(分裂)
2. 唯一索引叶子块+表块
6.Automatic Undo Management
Oracle 中保存了用于恢复对数据库操作的信息。例如事务(transaction)中所有操作的记录(被统称为undo)。Oracle可以利用undo完成以下工作:
- 回滚(rollback)一个活动的事务
- 恢复(recover)一个已结束的事务
- 实现读完整性(read consistency)
- 恢复语句的逻辑错误(logical corruptions)
自动撤销管理(automatic undo management)是基于撤销表空间(undo tablespace)的。用户使用undo tablespace管理undo信息,而不必创建多个大小不一的回滚段(rollback segment)。
自动撤销管理(automatic undo management)消除了管理回滚段(rollback segment)的复杂性,使用户只需专注于控制undo信息(undo)的保存期限。Oracle强烈建议用户使用undo tablespace,避免使用回滚段(rollback segment)。系统能够自动调整undo信息在undo tablespace内的保存时间,供需要使用undo信息的查询使用。如果正在使用的undo tablespace中有足够的空间,用户可以为 UNDO_RETENTION 参数设定一个最低阀值(low threshold value),这样系统中的undo信息至少在此值指定的时期内将被保留。
用户可以使用 V#UNDOSTAT 视图来监视撤销空间(undo space)的使用情况,并对对其进行配置以提高效率。V$UNDOSTAT 能够显示各种与undo空间及相关事务(transaction)有关的统计信息,例如当前实例(instance)中使用了多少undo空间。
提示:
Oracle的早期版本使用回滚段(rollback segment)来存储撤销信息(undo),即手动撤销管理模式(manual undo management mode)。对回滚段进行空间管理十分复杂,Oracle已经放弃了这种撤销信息的管理模式。
6.1.撤销管理模式
在自动撤销管理(automatic undo management)模式下,为事务提供撤销段(undo segment)及为此段分配空间的工作完全由数据库系统控制。然而一个存在问题的事务(ill-behaved transaction)有可能消耗大量撤销空间(undo space),甚至导致整个系统瘫痪。在资源管理器(Resource Manager)中可以设置 UNDO_POOL 参数,从而以更直接的方式控制大事务(large transaction)的管理。数据库管理员可以将用户编为消费者组(consumer group),并为每个组设定最大撤销空间限制。当一个组使用的撤销空间之和超过了设定的限制值时,这个组的用户就不能执行新的更新(update)操作,直到本组内其它用户的事务结束并释放撤销空间。
UNDO_POOL 参数的默认值是 UNLIMITED,即用户可以使用整个撤销表空间(undo tablespace)来存储其撤销信息。数据库管理员也可以使用 UNDO_POOL 参数对每一个用户进行限制。
另见:Oracle Database Administrator’s Guide,Chapter 24 Using the Database Resource Manager,了解关于 UNDO_POOL 的信息。
6.2.Automatic Undo Retention
Oracle 10g 数据库自动地调整用于控制撤销信息保存周期(undo retention period)的参数。撤销信息保存周期是指,撤销表空间中旧的撤销信息(即已提交事务的撤销信息)在被覆盖之前至少需要被保存的时间。数据库会收集撤销信息的使用情况,并根据统计结果及撤销表空间(undo tablespace)的大小对撤销信息保存周期进行调整。当数据库处于自动撤销管理(automatic undo management)模式下,其撤销信息保存周期的调整规则如下:
- 对于存储参数为 AUTOEXTEND 的undo tablespace,如果空间情况允许,数据库将undo信息保存周期设为比系统中最长的查询时间稍长。此外,如果空间情况允许,系统设定的undo信息保存周期不会低于 UNDO_RETENTION 初始化参数。
- 对于固定容量的undo tablespace,数据库将undo信息保存周期设为undo tablespace所支持的最大值。这意味着数据库可以使用接近undo tablespace极限的容量为用户提供最长的undo信息保存周期。The UNDO_RETENTION initialization parameter is ignored unless retention guarantee is enabled.
- undo信息保存周期的自动调整不适用于 LOB 数据。LOB 列的undo信息保存周期由 UNDO_RETENTION 参数决定。
当一个固定容量的undo tablespace与一个自动扩展的undo tablespace(存储参数为 AUTOEXTEND)容量相同时,前者使用的undo信息保存周期(undo retention period)调整方法通常能够提供更长的保存时间。这使闪回(flashback)操作可以追溯的更远,也使运行时间长的查询有更多的撤销数据(undo data )可用。
6.3.外部视图
用户可以使用 V#TRANSACTION 及 VROLLSTAT 视图监控事务(transaction )及撤销空间(undo)的信息。对于自动撤销管理(automatic undo management)模式,V#ROLLSTAT 视图能够展现自动撤销管理所使用的各个撤销段(undo segment)的情况。
VUNDOSTAT 可以显示撤销空间运行的历史统计信息。用户可以查询撤销空间使用率(undo consumption rate),事务并发性(transaction concurrency),实例中最长的查询的运行时间等统计信息。通过这个视图,用户可以更好地估计在当前工作负荷下系统所需的撤销空间(undo space)容量。
另见:
Oracle 数据库管理员指南 详细了解如何设置 UNDO_MANAGEMENT 参数,撤销信息保存周期自动调整,以及如何使用 V$UNDOSTAT 视图等信息