Oracle原理学习笔记_第1页
Oracle原理学习笔记_第2页
Oracle原理学习笔记_第3页
Oracle原理学习笔记_第4页
Oracle原理学习笔记_第5页
已阅读5页,还剩66页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

/ORACLE的工作机制体系结构实例Oracle运行的时候,在内存中会要开辟一个区间,这个区间主要是用于从磁盘(数据文件)中读出数据后的一个在内存的缓存和处理。而处理这些数据的操作,需要有一些系统的后台进程,这些进行在Oracle数据库启动的时候,就开始运行,一直在响应前台的操作。实际上,这一个区间(SGA)和这些后台进程合在一起,就称为实例。实例是包括SGA区和后台进程两个局部的。数据库启动执行若干动作,经历三个阶段,分别是未加载、加载和翻开。1、未加载(nomount)可以把数据库启动的这一阶段看作是Oracle实例的启动。这种方式启动下可执行:重建控制文件、重建数据库。这一启动命令:•读取数据库参数文件。•启动所需的后台进程并按参数文件中的定义分配内存。•将进展情况写入告警日志文件中。2、加载(mount)在实例启动加载阶段,数据库参数文件中指定的控制文件被读取。记住控制文件将数据库各局部联系在一起。实例从控制文件中找到以下信息,然后将进展写入告警日志文件。这种方式启动下可执行:数据库日志归档、数据库恢复、重新命名一些数据库文件:•所有数据文件和重做日志文件的名称和位置。•数据库名。•最新系统更改号(SCN)。3、翻开(open)包含在数据库中的每个联机数据文件在数据库翻开前必须被同步。在数据库翻开阶段:•所有联机数据文件的头与控制文件信息相比较。•所有文件同步后,数据库翻开。当数据库关闭时,取决于它的关闭方式执行不同的任务:•正常(normal)在所有的用户离线后发生的正常关闭。•事务(transactional)事务关闭就是当所有的用户执行完当前的事务后,将用户从数据库上去除。•立即(immediate)立即关闭就是从数据库去除所有当前用户之后,回退所有未完成的操作。•异常(abort)异常关闭没有给数据库任何整理的时机。这种方式关闭后需要实行崩溃恢复。实例是数据管理的核心—它做所有的工作,而数据库存储所有的数据。其他启动方式:•startuprestrict约束方式启动这种方式能够启动数据库,但只允许具有一定特权的用户访问非特权用户访问时,会出现以下提示:ERROR:ORA-01035:ORACLE只允许具有RESTRICTEDSESSION权限的用户使用•startupforce强制启动方式当不能关闭数据库时,可以用startupforce来完成数据库的关闭先关闭数据库,再执行正常启动数据库命令•startuppfile=参数文件名带初始化参数文件的启动方式先读取参数文件,再按参数文件中的设置启动数据库•startupEXCLUSIVE***************一个Delete操作的流程:检查语法、语义(V$ROWCACHE:datadictionarycache),计算HASHVALUE,在session的UGA中进行匹配(session_cached_cursors),如果UGA中没有,在librarychache中匹配(librarychachelocklatch保护librarychachelock对地址堆的访问,而后librarychachepinlatch保护librarycachepin对librarycache中sql相关信息的访问)根据执行方案读取数据:cachebufferchainlatch保护能定位到bufferheader并pin住该块(如果没有bufferheader,就pin住某个空块(没有空块就产生freebufferwaits),并到数据文件中读取)。如果此时有某个进程想访问该块,将产生bufferbusywaits。在redologbuffer中记录delete操作的细节。(包括回滚段前后镜像、数据块前后镜像)。在相应回滚段段头的事务表中创立一个undo条目,把将要删除的记录创立前镜像,存放到UndoBlock中。在BufferCache中的相应数据块上删除记录,并且标记相应的数据块为Dirty。提交(COMMIT)

1.Oracle产生一个SCN

2.在回滚段事务表中标记该事务状态为commited

3.LGWRFlushLogBuffer到日志文件

3.如果此时数据块仍然在BufferCache中,那么SCN将被记录到BlockHeader上,这被称为快速提交(fastcommit)

4.如果dirtyblock已经被写回到磁盘,那么下一个访问这个block的进程将会自回滚段中获取该事务的状态,确认该事务被提交。然后这个进程获得提交SCN并写回到BlockHeader上。这被称为延迟块去除(delayedblockcleanout)。内存SGA(系统全局区、共享全局区)、PGA(进程全局区、私有全局区)内存分配原则:10%冗余内存,OSSYS进程(约1.6G),OSBUFFER(约0.8G),数据库连接消耗内存(每个连接约5~8M),PGA(每个连接约2M,V$PGA_TARGET_ADVICE),SGASGAv$sgastat注意showparametersga_max_sizeOracle的内存:软件代码区系统全局区进程全局区:包含单个进程的数据和控制信息排序区

SGA中的Thefixedarea包含了数千个原子变量,以及如指向SGA中其它区域的pointers(指针)等小的数据结构.通过对fixedtable内表X$KSMFSV查询(如下)可以获得这些变量的名字,变量类型,大小和在内存中的地址.thevariablearea是由largepool和sharedpool组成Sharedpool中永久性的内存包含各种数据结构如:thebufferheaders,processes,sessions,transactionarrays,theenqueueresources,locks,theonlinerollbacksegmentarrays,variousarraysforrecordingstatistics.其中大局部的SIZE是依靠初始参数的设置来确定的.这些初始参数只能在实例被关闭的状态下才能够进行修改.所以这里说的永久性是针对实例翻开状态下的生存期而言.Thevariablearea的在SGA中的SIZES就等于LARGE_POOL_SIZE,SHARED_POOL_SIZE和永久性的内存arrays的SIZE三者相加.永久性内存arrays的SIZE=thevariablearea-(LARGE_POOL_SIZE+SHARED_POOL_SIZE).数据缓冲区命中率 v$sysstat 这里命中率的计算应该是 令x=physicalreadsdirect+physicalreadsdirect(lob) 命中率=100-(physicalreads-x)/(consistentgets+dbblockgets-x)*100 通常如果发现命中率低于90%,则应该调整应用可可以考虑是否增大数据缓冲区共享池的命中率 SQL>selectsum(pinhits-reloads)/sum(pins)*100"hitradio"fromv$librarycache; hitradio 99.809291 假设共享池的命中率低于95%,就要考虑调整应用(通常是没使用bindvar)或者增加内存关于排序局部 SQL>selectname,valuefromv$sysstatwherenamelike'%sort%'; NAMEVALUE sorts(memory)67935 sorts(disk)1 sorts(rows)7070 假设我们发现sorts(disk)/(sorts(memory)+sorts(disk))的比例过高,则通常意味着 sort_area_size局部内存较小,可考虑调整相应的参数。关于log_buffer SQL>selectname,valuefromv$sysstat 2wherenamein('redoentries','redobufferallocationretries'); NAMEVALUE redoentries2325719 redobufferallocationretries10 假设redobufferallocationretries/redoentries的比例超过1%我们就可以考虑增大log_buffer如何在Linux上扩展SGA超过1.7G共享池(SHARED_POOL_SIZE)v$shared_pool_adviceALTERSYSTEMFLUSHSHARED_POOLHowtoKeepObjects--重点使用DBMS_SHARED_POOL.KEEP过程来keepobjects,UNKEEP过程从sharedpool中移走pinnedobjectsexecutedbms_shared_pool.keep('address,hash_value');--keep该匿名块共享池包括库高速缓存(librarycache)、数据字典高速缓存和效劳器控制结构(例如数据库字符集)。Oracle效劳器用库高速缓存来提高执行SQL语句的性能;库高速缓存包括共享和专用SQL区。共享SQL区包括SQL语句语法分析树和执行路径,而专用SQL区存储特定的会话信息,例如捆绑变量、环境和会话参数、运行堆栈和缓冲区等。Softparse使用的资源包括CPU和librarycachelatchgetsHardparse是指要解析的SQL没有在librarycache中,或者执行的时候发现解析过的SQL已经agedout,就是离开了librarycache,称为Librarycachemisses.使用的资源包括额外的CPU,librarycachelatchgets,以及sharedpoollatchgets.专用SQL区在每个事务初始化时创立,在与专用SQL区相关的游标关闭时被释放。一个用户会话能够一次翻开的专用SQL区的数量由init.ora参数OPEN_CURSORS决定。使用这两个结构,Oracle效劳器能够重用一条SQL语句的所有执行的共同信息。与此同时,可以从专用SQL区中查询执行的特定会话信息。注意游标使用过程中并不关闭游标的应用会继续为应用分配越来越多的内存,局部原因是为每个翻开的游标分配了专用SQL区。库高速缓存中的专用SQL区可更进一步分为永久区和运行区。共享池的大小取决于init.ora文件参数SHARED_POOL_SIZE,它是以字节为单位的。你必须将这个值设得足够大,以确保有足够的可用空间来装载和存储PL/SQL块和SQL语句。共享区经过长期装卸和卸载数据对象会产生许多碎片,如果在共享池中没有足够的连续空间用来装载目标数据,会产生错误。解决这个问题的捷径是运行SQL命令ALTERSYSTEMFLUSHSHARED_POOL。但是如果在数据库操作时,经常遇到共享池错误,你必须增大共享池

Librarycache

包含sharedSQLandPL/SQLareas(PL/SQL包括Procedures,Functions,Packages,Trigger,匿名PL/SQL块)SizingtheLibraryCache定义storedobject(packages,views等等)的内存需求;定义经常使用的sqlstatement的所需内存1.初始时将SHARED_POOL_SIZE设得很大,运行应用程序2.计算storedobject所占的内存

SELECTSUM(sharable_mem)FROMv$db_object_cache

WHEREtype='PACKAGE'ortype='PACKAGEBODY'ortype='FUNCTION'ortype='PROCEDURE';3.应用程序运行一段时间后,估计常用sql语句所占的内存(不包括动态SQL)

SELECTSUM(sharable_mem)

FROMv$sqlarea

WHEREexecutions>5;4.对每个user每个翻开的cursor,需要250bytes,可在运行顶峰期间使用查询:

SELECTSUM(250*users_opening)FROMv$sqlarea;5.在测试环境中,可让一个用户翻开一定数量的cursor,运行以下语句测试共享内存,然后乘上user数

SELECT250*valuebytes_per_user

FROMv$sesstats,v$statnamen

WHEREs.statistic#=n.statistic#

AND='openedcursorscurrent'

ANDs.sid=15;以上内存的和,再加上一点内存(留给动态SQL使用),作为你的应用的理想内存设置;预留一局部空间作为大的内存需要,防止miss和碎片;一些大的内存需要:PL/SQL块的编译,trigger的编译;小的object不会使预留空间碎片化,反而保证reservedlist有大的连续块,一旦从reservedlist中分配的内存释放它就返回reservedlist。影响的参数:SHARED_POOL_RESERVED_SIZE

初始值=SHARED_POOL_SIZE*10%,超过50%,oracleserver报错OPEN_CURSORS缺省=50定义了涉及分配给用户进程的私有SQL区域的cursors数量,一个privateSQLarea一直存在直至cursor关闭;为了利用更多的内存给共享SQL区域,需要提高session每个session允许多cursor数量,开发人员应关闭不需要的cursor节省内存CURSOR_SPACE_FOR_TIME缺省=FALSE布尔值设置TRUE,表示以空间换取时间,共享SQL区不会被agedout直至相关的cursor被关闭,因此确信有足够的内存,没有cachemiss;除非RELOADSinV$LIBRARYCACHE一直为0,否则不要改变此参数值若应用为FORM或使用动态SQL,设此值为FALSE--因为动态sql总是不一致,将占用过多内存SESSION_CACHED_CURSORS缺省=0表示没有cache当一个session打算关闭一个cursor时,如果这个cursor的parsecount超过3次,那么这个cursor将会被加到sessioncursorcachelist的MRU端.当一个session打算parse一个sql时,它会先去session的pga内搜索sessioncursorcachelist,如果找到那么会把这个cursor脱离list,然后当关闭的时候再把这个cursor加到MRU端.session_cached_cursor提供了快速软分析的功能,提供了比softparse更高的性能.检查系统是否需要此参数的方法:对某个典型用户sessionselecta.sid,,a.valuefromv$sesstata,v$statnamebwherea.statistic#=b.statistic#and(='sessioncursorcachehits'orlike'parsecount%');Iffewparsesresultinhits,则可提高此参数,注意它将increaseoveralldemandsonmemory.--????DataDictionaryCacheSelecttype,parameter,gets,getmisses,round(getmisses/decode(gets,0,null,gets)*100,2)"ratio(%)"fromv$rowcache;GoalforaGoodRatioSUM(GETMISSES)/SUM(GETS)<15%,否则应增大SHARED_POOL_SIZE不可能希望getmisses趋近于0,因为数据库启动后需要读取objects定义OEM-->PerformanceManager—>Memory—>DataDictionaryCacheHit%检索需要在共享池中要求大于100K连续空间的对象:select*fromv$db_object_cachewheresharable_mem>100000andtypein('PACKAGE','PACKAGEBODY','PROCEDURE','FUNCTION');考察返回的结果,确认是否需要pin到共享池中,返回结果中的KEPT字段如果是YES,那么表示该对象已经固定在了共享池中,为NO,则表示还没有固定。如果需要固定,使用下面的语句:execdbms_shared_pool.keep('SYS.STANDARD');数据库默认安装的时候没有创立dbms_shared_pool包,所以需要先创立该包。cd$ORACLE_HOME/rdbms/adminsqlplus“/assysdba〞@dbmspool.sqlDATABUFFER数据库缓冲区高速缓存v$db_cache_advice==一堆数据块(DB_BLOCK_SIZE*DB_BLOCK_BUFFERS)数据库的任何修改都在该缓冲里完成(LRU-->LRUW)。所有的块,被读到内存中后,它的块头(datablockheader)放在一个Cachebufferchain中,Cachebufferchain由多个双向hash链表组成,hash链表数量由_db_block_hash_buckets决定.每个数据块头由DBA(datablockaddress)作为key,经hash函数后放在链表上,它和blockbuffer中的block一一对应,数据块头不包括实际的数据,仅是一个简单的描述.后台进程扫描hash链表前,必须获得cachebufferchainlatch,如果在CacheBufferchain中找不某块,就由磁盘读入.若需要查找某个block,则根据block的信息能计算hashvalue然后迅速定位到hashtable,然后根据hashtable信息去查看是否存在所想要的buffer,若有则命中,若没有则不命中。显然不可能根据list去逐个搜索,这样效率太低.LRU就是一种尽可能将常用的数据保存在内存的算法.当数据库需要一个数据缓冲区,他会从数据库缓冲区的LRU队列的尾部找一个空闲的缓冲,将一个数据块读入,然后数据库会把这个缓冲区放到LRU队列的中部,如果该缓冲被其他程序用到的话,那么他会往队列的头上移动,如果这个缓冲没有被其他程序用到,并且没有被修改正,那么他会慢慢的移动到LRU队列的尾部,最终被认为是空缓冲区被其他数据块所覆盖.一旦这个缓冲区被修改正DBWR把他从LRU队列中移出,放到LRUW队列(也叫赃缓冲区)中,等待DBWR把他们批量写入数据文件,然后再把他们的缓冲区连接到LRU队列的尾部.周而复始的工作.如果查找在一个阀值内没有结果或者造成dirty缓冲区已经溢出,在进一步查找freebuffer前系统将发出一个消息给DBWR让他可以将LRUW队列的缓冲区写入磁盘.这个阀值被叫做这个阀值被叫做DBWRscandepthdirty缓冲区大小可以用_DB_LARGE_DIRTY_QUEUE和2*_DB_BLOCK_WRITE_BATCH来确定.前台进程继续搜索freebuffer.直到_DB_BLOCK_MAX_SCAN_CNT还没有发现系统就会挂起该进程.记录dirtybuffersinspected的静态变量并把该进程标志为freebufferwait.cache和buffer_pool_keep是不一样的,cache是如果对该表全表扫描的话,会把块放在mru端,buffer_pool_keep是放在keep池中selecttable_name,cache,buffer_poolfromdba_tableswheretable_name='TEST';将表和索引Cache到SGA中从ORACLE805之后,支持ALTERTABLEtable_nameSTORAGE(BUFFER_POOLKEEP)命令了。

但是在805与8i中,需要设置buffer_pool_keep参数来设置KEEP池大小。这块内存来自数据缓存区,也就是从db_block_buffers中分配。在ORACLE8和8i中,还必须设置db_block_lru_latches参数。该参数应该比2*3*CPU数量少,但是要大于1,否则无法设置buffer_pool_keep。在ORACLE9i中则需要设置DB_KEEP_CACHE_SIZE来设置KEEP池内存的大小。这样将表KEEP才有用。而且KEEP池要能够容纳得下才行的将函数Cache到SGA中@$ORACLE_HOME\rdbms\admin\dbmspool.sql;execdbms_shared_pool.keep('procedure_name','P');重做日志缓冲区(LOG_BUFFER)logbuffer分成内部的bufferblocks,而这些block各有8个字节的头部信息存在于variablearea中.当重做日志缓冲区填满时,将它的内容写入联机重做日志文件。是循环使用。是数据库最活泼的情形,可以用V$SYSSTAT视图进行监控。查询V$SYSSTAT视图value域,它说明用户进程等待重做日志缓冲区所花费的时间(此处value的值应接近于0,否则应增大初始化参数文件的Log_buffers的值):SELECTNAME,VALUEFROMV$SYSSTATWHERENAME='redologspacerequests';PGAv$pgastatv$pga_target_advice后台进程v$bgprocess■数据库写进程(DBWR)(DB_BLOCK_WRITE_BATCH,DB_BLOCK_MAX_SCAN,DB_WRITES,DB_BLOCK_LRU_LATCHES,DB_BLOCK_CHECKPOINT_BATCH,DB_BLOCK_CHECKSUM)负责数据文件的读写和db_data_buffer的清理dbwr负责搜集dirtybuffer,slaves负责写磁盘工作的前提条件:1.dirtybuffer超出了dirtybufferlist的threshold.

2.serverprocess在buffercache中查找freebuffer时,则也可能会通知DBWn将dirtybuffer写入datafile.

3.DBWn每3秒会检查是否有dirty数据要写入datafile.

4.CKPT

5.tablespaceoffline或tablespacebeginbackup(这里实际上是由CKPT引起).

6.dropobject

7.shutdown(这里实际上也是由CKPT引起)建议你使用与存储数据文件的物理磁盘一样多的DBWR进程;DBWR写入数据文件的任何修改已经被记录在重做日志文件中.一次checkpoint的成功过程是:dbwr搜集dirtybuffer,交给slave写磁盘,写完毕通知dbwr,然后dbwr才返回检查点完成。增加写进程,同时要调整db_block_lru_latches参数,如修改或添加如下两个参数: db_writer_processes=4 db_block_lru_latches=8■日志写进程(LGWR)。 LOG_CHECKPOINT_INTERVAL,LOG_CHECKPOINT_TIMEOUT,LOG_CHECKPOINTS_TO_ALERTLGWR工作的主要条件如下1.用户提交2.有1/3重做日志缓冲区未被写入磁盘3.有大于1M重做日志缓冲区未被写入磁盘4.超时5.DBWR需要写入的数据的SCN号大于LGWR记录的SCN号,DBWR触发LGWR写入■归档进程(ARCH)。 ARCHIVE_LOG_START■检查点(CKPT)。同步数据文件,日志文件和控制文件CKPT会更新数据文件/控制文件的头信息.CKPT工作的主要条件如下1.在日志切换的时候2.数据库用immediate,transaction,normal选项shutdown数据库的时候3.根据初始话文件LOG_CHECKPOINT_INTERVAL、LOG_CHECKPOINT_TIMEOUT,FAST_START_IO_TARGET的设置的数值来确定4.用户触发■系统监控和进程监控进程(SMON和PMON)。■调度进程(Dnnn)。 MTS_DISPATCHERS■恢复进程(RECO)。 DISTRIBUTED_TRANSACTIONS■快照进程(SNPn)。 OB_QUEUE_PROCESS,JOB_QUEUE_INTERVAL■锁进程(LCKn)。 ■并行查询进程(Pnnn)。 PARALLEL_MIN_SERVERS,PARALLEL_MAX_SERVERS■用户和效劳器进程(Snnn)。回滚v$rollstatv$waitstatv$sysstatx$bhdba_rollback_segs一下事务的流程:1.分配一个回滚段

2.在回滚段事务表中分配一个事务槽

3.分配undoblock

4.更新数据块上的ITL事务槽

5.把前镜像记录在undoblock内

6.更改数据块的内容ITL事务槽--InterestedTransactionList(ITL)ITL内容包括:xidTransactionIDUbaUndoBlockAddressLckLockStatusxid=Undo.Segment.Number+Transaction.Table.Slot.Number+Wrapuba=Address.Of.Last.Undo.Block.Used+Sequence+Last.Entry.in.UNDO.Record.MapALTERSYSTEMSETUNDO_MANAGEMENT=MANUALSCOPE=SPFILE;SETTRANSACTIONUSEROLLBACKSEGMENTRB_LARGE1;当一个事务开始的时候,会首先把变化前的数据和变化后的数据先写入日志缓冲区,然后把变化前的数据写入回滚段,最后才在数据缓冲区中修改数据一致性读取consistentreads假设查询开始的时候的SCN为T,则在查询所扫描的数据块中,如果数据的COMMITSCN小于T,则查询接受该数据,如果COMMITSCN大于T或者说还没有产生COMMITSCN,则查询会尝试去回滚段中查找数据。这是为了保证数据的读取的时间点的一致性,所以叫一致性读。我们可以参考v$rollstat、v$transaction和x$bh表,在x$bh中的class字段,如果是回滚段块,假设回滚段USN为n,则回滚段头class为11+2n,回滚段块为12+2n。回滚段的使用、扩展、回缩同一个事务不能跨越回滚段;一个回滚段至少包含2个extent。每个回滚段有一个回滚段头,回滚段头是一个block,里面主要记录了事务表信息。当产生一个事务的时候,就在回滚段头的事务表中记录一条信息,该信息中包含了事务标志、事务状态、使用的回滚段块数等等信息。使用时从第一个extent的第二个block到最后一个extent循环使用;如果其中的一个extent有未提交的事物,那么前面的extent不能跨越该extent,只能在2个extent之间扩展新的extent,并修改相应的节点指针(回滚段的extent之间是通过指针连起来的一个单向循环的链表结构);系统回滚段与延迟回滚段SYSTEM回滚段是创立在系统表空间中,主要是用于系统级的事务和分配普通事务于其他回滚段上。当手工创立数据库后需要创立普通回滚段之前必须首先创立系统回滚段。系统回滚段主要用于两个方面。一是系统事务,比方针对数据字典的操作的truncatetable和droptable。如果truncatetableordroptable的过程中没有成功,则系统会根据系统回滚段中的数据字典操作信息对该DDL操作进行回退。另一个方面,就是延迟回滚段(DeferredRollbackSegment)。表空间offline时用户申请回滚,数据库会将回滚信息写入系统回滚段(就是延迟回滚段),等到online时,在写入表空间。回滚段的设置和管理init.ora:transactions_per_rollback_segment和transactions,max_rollback_segments1:系统并发事务数有多少?(主要是产生恢复信息的会话数+一局部冗余数(20)=总回滚段数)2:系统是否存在大查询或者大是事务?频繁么?3:能提供给系统的回滚段表空间的磁盘空间是多少?不要将回滚段的MAXEXTENTS设为UNLIMITED,回滚段所在表空间也不要设为AUTOEXTEND方式,否则将会使得由于某个不正常的事务导致整个数据库处于失控状态。9iundo_retention表示在自动管理模式下,回滚段中的数据在被覆盖前保存多长的时间,单位是秒。这个参数应该决定于系统所中一些大查询运行的时间长度,以防止ORA-01555错误。在9i下创立非自动管理的的回滚段而不使用UNDO表空间,则设置undo_management为MANUAL,然后在系统表空间中创立一个回滚段(注意这是必须的),创立自己的回滚段表空间,这时可以在回滚段表空间中创立回滚段,创立完毕删除系统表空间中的回滚段。著名的ORA-01555问题一致读获取的时候发现回滚段已经被覆盖而出现找不着变化前映像,也就是当COMMITSCN大于T查询尝试去回滚段中找回数据却发现回滚段已经被覆盖了(因为回滚段是循环使用的),则会出现著名的ORA-01555错误。重做v$sysstatv$logv$logfilev$log_historyaltersystemswitchlogfile;重做记录了块的改变,包括回滚段头块、回滚段块、数据块,并且在块改变之前先记录重做信息。更改矢量(changevector)—当要改变数据库的数据时,这些改变的细节被记录为更改矢量。通过这些记录,数据库处理过程可以被重现。简而言之,一个更改矢量就是记录了一个数据块的行槽从一个状态改变到另一个状态的过程。也就是redo的记录单位是entry,即:Y,rowslotZ。Redo也记录了数据块(tableblock&indexblock)前照,其实记录的就是undo,因为即使没有commit,改动也会被记录到redo文件里,这时的tableblock&indexblock就是未提交的最新状态,如果此时系统崩溃,则需要redo中记录的undo(前照)进行恢复,所以redo记录了数据块、索引块、回滚块。ORACLE推荐logswitch时间最好在15--30分钟之间。跟redologfile有关的其它数据库参数1、log_buffer它最好不要大于512K或者128K*CPU个数。我们可以用下面的SQL语句检测log_buffer使用情况:SELECTRBAR.NAME,RBAR.VALUE,RE.NAME,RE.VALUE,(RBAR.VALUE*100)/RE.VALUE||'%'"radio"FROMV$SYSSTATRBAR,V$SYSSTATREWHERERBAR.NAME='redobufferallocationretries'ANDRE.NAME='redoentries';这个比率小于1%才好,否则增加log_buffer的大小2、log_checkpoint_intervalOracle8.1版本后log_checkpoint_interval指的是两次checkpoint之间操作系统数据块的个数。checkpoint时Oracle把内存里修改正的数据块用DBWR写到物理文件,用LGWR写到日志和控制文件。从性能优化来说log_checkpoint_interval=redologbytes/512bytes3、log_checkpoint_timeoutOracle8.1版本后log_checkpoint_timeout指的是两次checkpoint之间时间秒数。

Oracle建议不用这个参数来控制,因为事务(transaction)大小不是按时间等量分布的。用log_checkpoint_interval参数控制会好一些。禁用此参数或者按默认的900。altersystemarchivelogcurrent;第二个存档日志目的地可以通过初始化参数LOG_ARCHEVE_DUPLEX_DEST设定。LOG_ARCHEVE_DEST和LOG_ARCHEVE_DUPLEX_DEST都可以存档所有的联机重作日志文件。另一个初始化参数LOG_ARCHIVE_MIN_SUCCEED_DEST如果设置了的话,可以决定一个重作日志组必须被成功存档到的存档日志目的地数,在一个目的地满或其介质有错时,该参数可以防止Oracle被冻结。要确保这两个目的地被配置在两个别离的磁盘/控制器上,防止I/O冲突对数据库性能的影响。一些参数v$parameter查看系统当前使用的所有参数SETpagesize9000SETheadOFFSETtermOFFSELECTDECODE(isdefault,'TRUE','#')||DECODE(isdefault,'TRUE',RPAD(name,43),RPAD(name,45))||'='||valueFROMv$parameterORDERBYname;查看所有参数是否已被init.ora重新设定SELECTname,isspecifiedFROMv$obsolete_parameter;查看过时参数和强调参数SELECTkspponm,DECODE(ksppoflg,1,'Obsolete',2,'Underscored')FROMx$ksppoORDERBYkspponm;查看当前系统中的所有隐藏参数(以sys身份登录)SELECTksppinm,ksppstvl,ksppdescFROMx$ksppix,x$ksppcvyWHEREx.inst_id=userenv('Instance')andy.inst_id=userenv('Instance')andx.indx=y.indxandx.ksppinmlike'%_&par%'orderbytranslate(x.ksppinm,'_','');用户参数select*fromv$fixed_tablewherenamelike'%NLS%';SELECT*FROMV$NLS_PARAMETERS;ALTERSESSIONSETNLS_DATE_FORMAT='YYYY-MM-DDHH24:MI:SS';最常被修改的参数:Shared_pool_size 分配给共享池的内存字节数随着用户的需求,可以按时增加此值Rollback_segments 数据库启动时获取的一个或多个当事务处理量增加或减少时,可以从该回滚段名列表中增加或删除回滚段名Processes 可同时访问数据库的最大进程数量session=1.1*process+5,一般而言,session和process是一一对应的,5是Oracle后台进程的session,10%是提供给recursivesession使用的。db_block_buffers 见SGA介绍中的相关内容shared_pool_size 见SGA介绍中的相关内容log_buffer 见SGA介绍中的相关内容sort_area_size针对每个session,排序首先会使用sort_area_size,如果缺乏则会使用临时表空间。实际上就是外排序过程,把要排序的对象分割为内存可以容纳的小段(sortrun),然后每个sortrun都放到sortarea里面去排序,排序结果作为中间信息放在临时表空间的临时段内,由于分段排序的结果当然不会是最终要求的排序结果,所以还要经过一个merge的过程,才会得到最终排序结果,原理大概是比较每个sortrun的第一名,取出领先者,然后该sortrun的第二名顶上,继续上述过程直到取完。所以建议:sort_area_size所能容纳记录数至少大于排序记录数的平方根5.open_cursor 见SGA介绍中的相关内容6.database_writers许多DBA有个错误的概念,认为此参数受CPU数量的限制,实际并非如此。提示:如果工作在一个可以支持多进程的操作系统上,需做的第一件事就是改变这个参数的值。重新启动数据库,使用startup命令,Oralce将会按照以下顺序在缺省目录中搜索参数文件:spfile${ORACLE_SID}.ora缺省目录UNIX:${ORACLE_HOME}/dbs/NT:${ORACLE_HOME}\databasesp 缺省目录UNIX:${ORACLE_HOME}/dbs/NT:${ORACLE_HOME}\databaseinit${ORACLESID}.ora缺省目录UNIX:${ORACLE_HOME}/dbs/NT:${ORACLE_HOME}\databaseor${ORACLE_HOME}\admin\db_name\pfile\创立了spfile,重新启动数据库,Oracle会按顺序搜索以上目录,spfile就会自动生效。startuppfile='E:\Oracle\admin\eyglen\p';createsppfile;然后我们可以使用ALTERSYSTEM方式将修改固定到SPFILE.ALTERSYSTEMSETlog_archive_start=FALSESCOPE=spfile;空间管理主体思想一直围绕着内部段的扩展。不仅仅影响到空间大小,自由块太分散的话会影响性能(I/O,及扩展时间等)空闲表(主空闲表、进程空闲表、事务空闲表),可能存在于表头块中表空间droptablespace***includingcontents;注:LMT是segment中extent的管理,ASSM是thefreespaceofsegment的管理。在Oracle8I的版本中,Oracle推出了一种全新的表空间管理方式:本地化管理的表空间。所谓本地化管理,就是指Oracle不再利用数据字典表来记录Oracle表空间里面的extent的使用状况,而是在每个表空间的数据文件的头部参加了一个位图区,在其中记录每个extent的使用状况。每当一个extent被使用,或者被释放以供重新使用时,Oracle都会更新数据文件头部的这个记录,反映这个变化。Oracle之所以推出了这种新的表空间管理方法,这种表空间组织方法的优点:1.本地化管理的表空间防止了递归的空间管理操作。而这种情况在数据字典管理的表空间是经常出现的,当表空间里的区的使用状况发生改变时,数据字典的表的信息发生改变,从而同时也使用了在系统表空间里的回滚段。

2.本地化管理的表空间防止了在数据字典相应表里面写入空闲空间、已使用空间的信息,从而减少了数据字典表的竞争,提高了空间管理的并发性

3.区的本地化管理自动跟踪表空间里的空闲块,减少了手工合并自由空间的需要。

4.表空间里的区的大小可以选择由Oracle系统来决定,或者由数据库管理员指定一个统一的大小,防止了字典表空间一直头疼的碎片问题。

5.从由数据字典来管理空闲块改为由数据文件的头部记录来管理空闲块,这样防止产生回滚信息,不再使用系统表空间里的回滚段。因为由数据字典来管理的话,它会把相关信息记在数据字典的表里,从而产生回滚信息。由于这种表空间的以上特性,所以它支持在一个表空间里边进行更多的并发操作,并减少了对数据字典的依赖。对于表空间中的每一个空间(一个或多个extent),我们必须知道:1、这个可用空间位于什么数据文件2、这个空间的尺寸是多大3、如果它在用了,是哪一个段占用的这个空间直到8i之前,所有的表空间都是采用字典管理模式,为了确保能保存以上的信息,ORACLE用了两个数据字典表:UET$(已使用的区间)或FET$(空闲空间):当一个段被删除的时候,ORACLE就移动UET$中相应的行到FET$,这个过程的发生是连续的,而且可能发生等待。当并发性很高的时候,数据字典的争用就来了。另外有一个问题就是,当表的空间很不连续或表空间有大量的碎片引起这两个表的增大,那么也就会引起数据库性能上的下降。表空间分段:气泡(bubble):一个连续的自由空间块;蜂窝(honeycomb):一系列看起来相连的块。蜂窝由气泡构成(气泡间有边界),去掉边界,蜂窝并成一个大的气泡。气泡和蜂窝多是由于扩展段的释放而产生。过多的小的气泡会导致DDL操作时屡次扫描SYS.FET$,并花时间合并可用空间,影响性能。让我们看一下当一个行被从一个应用程序中插入到表中时发生的一系列动作:1)查表的自由列表,考虑在哪可以放一个新行。如果没有自由块可用,需要分配一个新的扩展段。2)Oracle扫描SYS.FET$表,为空间中的扩展段定位自由空间。3)第一次扫描找出可以供新的扩展段使用的气泡。新扩展段的大小计算使用大于扩展段所需块数的、下一个可被5整除的数。例如,如果一个扩展段包含23块,则得到的数是25块。然而,如果需要的是5块或更小,就不必这样计算,一旦块数确定,第一次扫描就寻找块数恰好满足需要的气泡。4)如果没有找到恰好适宜的,那么Oracle扫描大些的气泡。如果一个大的气泡所拥有的块数比所需要的块数多5块或5块以上(当然是在取了约数以后),那么气泡中的自由空间分成两局部,一局部满足扩展段的需要,另一局部仍作为自由空间。新的(小一些的)的自由空间气泡包括去掉所需的块数后剩下的块数(5块或多于5块)。例如,如果需要的块数是25,但找到了一个32块的气泡,那么Oracle占用其中的25块分配给扩展段并保持剩下的7块形成一个分开的气泡,仍然保存在原处。另外一种情况,找到了一个28块的气泡,那么只是把此气泡供扩展段使用。换句话说,如果多余的块数少于5就不产生分割操作。5)如果所有现有的气泡都太小,缺乏以满足扩展段的需要(即没有找到大小相等的也没有找到大于数据块数的气泡),那么进行第三次扫描寻找是否有可以合并的蜂窝能提供所需的空间。在合并以后,再次进行第3步和第4步。6)如果前面的几步都没有找到能够供扩展段使用的气泡,那么Oracle检查AUTOEXTEND功能是否已被使能(后面详细介绍这一选项)。如果是的,再检查数据文件是否是可扩展的。7)如果AUTOEXTEND没有被使能或者在磁盘上(数据文件所在的磁盘)没有足够的空间来扩大该数据文件,Oracle返回“ORA-1650-55:Unabletoextend〞错误消息,引起应用失败。预防措施:1)将大小相同而且增长率相似的段应该保存在相同的表空间集合中,保证释放的气泡可以高效地被别的段重新使用。2)理想情况下,一个表空间中的所有段应该有相同的存储参数(对每一个段有相同的INITIAL/NEXT值)。如果不能做到这一点,要保证不同段的存储参数要互为倍数。为所有的表空间指定DEFAULTSTORAGE参数。3)一旦可能,指定PCTINCREASE=0。当由于没有定义增长模式而不可能指定该值时,用100作为PCTINCREASE的可能值。在任何情况下,不要用如1、5等的随机值,以防止生成奇数大小的扩展段。4)周期性显式地合并应用程序的表空间。不要配置SMON来自动合并表空间,因为它需要在表空间的DEFAULTSTORAGE语句中指定一个大于0的PCTINCREASE的值。识别表空间段情况、重构特定文件:1)识别表空间中的扩展段、气泡、蜂窝:SETLINES132SETPAGES500COLUMN“FIL_ID〞FROMAT999HEADING“FIL|ID〞COLUMN“FIL〞FORMATA55HEADING“FIL-NAME〞COLUMN“SEGMENT〞FROMATA55COLUMN“STARTBLK〞FROMAT999999HEADING“START|BLK〞COLUMN“#BLOCKS〞FORMAT999,999HEADING“#|BLKS〞SELECTD.“FIL_ID〞,D.“FIL〞,SEGMENT_TYPE||‘‘||OWNER||‘,’||SEGMENT_NAME“SEGMENT〞,E.BLOCK_ID“STARTBLK〞,E.BLOCKS“#BLOCKS〞FROMDBA_EXTENTSE,DBA_DATA_FILESDWHEREE.TABLESPACE_NAME=UPPER(‘&&TBLSPC_NAME’)ANDD.TABLESPACE_NAME=E.TABLESPACE_NAMEANDD.=E.UNIONSELECTS.“FIL_ID〞,D.“FIL〞,‘FREECHUNK’“SEGMENT〞,S.BLOCK_ID“STARTBLK〞,S.BLOCKS“#BLOCKS〞FROMDBA_FREE_SPACES,DBA_DATA_FILESDWHERES.TABLESPACE_NAME=UPPER(‘&&TBLSPC_NAME’)ANDD.TABLESPACE_NAME=S.TABLESPACE_NAMEANDD.=S.ORDERBY1,4,5/结果:FIL_IDFILSEGMENTSTARTBLK#BLOCKS1/opt/app/oracle/oradata/orcl/system01.dbfROLLBACKSYS,SYSTEM2101/opt/app/oracle/oradata/orcl/system01.dbfROLLBACKSYS,SYSTEM12101/opt/app/oracle/oradata/orcl/system01.dbfCLUSTERSYS,C_OBJ#22201/opt/app/oracle/oradata/orcl/system01.dbfINDEXSYS,I_OBJ#4221/opt/app/oracle/oradata/orcl/system01.dbfCLUSTERSYS,C_TS#4421/opt/app/oracle/oradata/orcl/system01.dbfINDEXSYS,I_TS#4621/opt/app/oracle/oradata/orcl/system01.dbfCLUSTERSYS,C_4831/opt/app/oracle/oradata/orcl/system01.dbfINDEXSYS,I_5121/opt/app/oracle/oradata/orcl/system01.dbfCLUSTERSYS,C_USER#5322)如果有大量的气泡分散在表空间中,特别是有许多小的气泡不能供任何扩展段使用时,那么就需要重建数据文件。3)根据停工时间决定重构方案,重构步骤:a)保存这些段中的数据(把数据输出或用CREATETABLEASSELECT命令来保存表数据;对于索引表,用CREATEINDEX脚本来重构它们)。b)丢弃数据文件中的段。c)用ALTERTABLESPACECOALESCE命令合并属于数据文件的表空间。d)在表空间中重建段。e)重新支持访问语句,检查分段情况,保证所有的段已经安排得很紧密,已经消除了大规模的分段。Oracle扩展段分配算法:用光那些看起来以后不会被使用的块!(比方扩展段外最后的几个块)DB_×DB_BLOCK_SIZE与INITIAL/NEXT:保证DB_BLOCK_SIZE和扩展段大小(INITIAL/NEXT)相适应,增强了每次I/O操作读尽可能多的数据的可能性(DB_×DB_BLOCK_SIZE);而不受到了扩展段结尾,只能读取扩展段中剩下的几块的限制。举个例子,可以更好地理解这一点:如果一个表包含5个扩展段,每个包含128个8K的数据块(即,INITIA&NEXT=1MB),那么在一次全表扫描中需要读5MB或5120KB数据。如果DB_是8(DB_BLOCK_SIZE是8K),那么理论上需要的最大I/O数为80次来读整个表(5120K/(8K×8))。这样,每个扩展段需要16次I/O调用。或者,如果使用一个不同的INITIAL/NEXT大小,那么I/O调用的次数会变化。例如,如果INITIAL&NEXT=520KB),那么在全表扫描期间需要读2.45MB或2600KB数据。假定,DB_仍是8,那么理论上需要多达45次I/O调用才能访问整个表。因为第二个表(2600KB)大约是第一个表(5120KB)的一半,可以假定,要读整个表的话,小表理论所需的I/O次数大约是大表的一半。然而,总共只做了5次I/O调用与假定的情况有很大的出入。让我们仔细分析一下当第二个表被扫描时到底发生了什么情况。在第二个表中的每个扩展段包含520K(2600K/STORAGE)或65个数据块。现在按假定的DB_在一次I/O调用中至多可读64K数据。因此,访问每个扩展段需要9次I/O调用读取了段中的98%的数据或64块,而第9次调用读取最后一块)。因为第9次调用只读取了8K(最后一块),所以不是最优的。这5个扩展段中的每一个都需要用第9次访问来读取其中最后一块,导致了5次附加的I/O调用。如果INITIAL/NEXT的大小调整得好一些,是(DB_BLOCK_READ_COUNT×DB_BLOCK_SIZE)的倍数,那么附加的5块可以在一次I/O调用中读入。例如,如果INITIAL/NEXT=512K,那么仅需要41次I/O调用来扫描整个表,节省了4次调用。这里,我们假定每个段有5个扩展段。然而,随着数据库变得越来越大,扩展段数会相当高,这样,相应地I/O调用也会增加。因此,在指定INITIAL/NEXT大小时考虑DB_BLOCK_SIZE非常重要。另外一个重要的参数,DB_,通常指定为8、16、32等等,以到达OS每次I/O调用的最大值。因此,通常该值与DB_BLOCK_SIZE值一致来提供最优的I/O。周期性地合并应用程序表空间:由SMON进程进行:ALTERTABLESPACECOALESCEALTERSESSIONSETEVENTS‘IMMEDIATETRACENAMECOALESCELEVEL&<表空间号>’;表空间的重组:因为当前磁盘空间满了,而手头又没有新的磁盘,所以需要重组表空间(减小同一磁盘其他表空间的大小,腾出空间),重组之前需要做好充足准备,相关操作见24X7第12.1.16;但在Oracle8i以后,支持可移动的表空间,所以不必进行复杂的重组。在进行表空间改组前要注意如下一些事项:•要保证移动睡眠表空间(或通过减少临时表空间)能提供所需要的空间(这是整个重组操作的目的之所在)。同样,如果临时表空间确实减少了,保证变小了的临时表空间仍然能满足先前所支持的应用程序的要求。•中选择一个睡眠表空间,丢弃或非联机时,应该保证其当前并不被用户使用。一个表空间可能当前看起来是“睡眠的〞(如,在白天)。然而,却可能被在晚上运行的批处理作业使用。另外,它也可能被CFO使用,而CFO今天未启动而已。因此,在决定哪个表空间是睡眠的之前要估计这种使用的可能性。•当被丢弃或使非联机的睡眠表空间中有某些相关的表时,要保证不发生访问整体性的冲突。•保证睡眠的表空间中不包含某些活泼表的索引。•保证睡眠的表空间中没有数据字典段(由于编辑了SQL.BSQ文件)。•保证在睡眠的表空间中没有回滚段。•要提供足够的提示信息告知用户这种“睡眠〞的表空间临时不可用,这样在删除操作前,可以注意到这一点。•在任何情况下,保证在重组之前和之后要备份控制文件。当允许文件自动增长时需要特别小心。对AUTOEXTEND的文件限制MAXSIZE小于2GB是明智的。否则,由于[BUG:568232],当文件增长超过ORACLE不能处理时可能会出现ORA-600[3292]等错误。表控制扩展段数目(<100),太大影响空间管理性能并增加数据字典记录允许扩展段(EXTENT)随时间增长,如按月、季度、年,由此调节INITIAL/NEXT需要并发时:INITRANS至少等于FREELISTmaxtrans:同一个block中允许最大并发事务数initrans:同一个block中至少允许这么多并发事务数,也就是一开始就保存这么多个事务需要的空间。(即ITL的个数,这样可以不用等到其他事务释放ITL)PCTFREE/PCTUSEDPCTINCREASE一般设为0MAXEXTENTS一般设为UNLIMITED控制非回滚段的段扩展频率,动态空间管理产生的递归调用会严重影响性能。带有ASSM的本地管理表空间会略掉任何为PCTUSED、NEXT和FREELISTS所指定的值。表的位置标记:指曾经有数据的最大块数(比方很多数据,后来删了,但是标记并没有减小),为5的倍数(如果只用1块,也会出现4个空块),全表扫描期间来确定读哪些块,可以用索引扫描代替全表扫描来防止访问已经没有数据的块;用ALTERTABLEDEALLOCATEUNUSED可释放MINEXTENTS外的未用空间,使用KEEP参数可以释放INITIAL/MINEXTENTS中的未用空间,并相应调节INITIAL/MINEXTENTS大小。表拥有的总块数(USER_SEGMENTS.BLOCKS)-未使用的空块数(USER_TABLES)-1=位置标记实际包含数据的块数:USER_TABLES.BLOCKS如果标记差异度过大且频繁使用,需要重建表TRUNCATE:•在段上获得一个独占锁(对段头块可以独占访问)。如果另外一个事务当前正向表中写(行一级或表一级的锁),那么截断操作必须通过在共享模式下申请一个TX锁等待。•把这个表中的所有块从缓冲区cache中写到磁盘上。•释放超过MINEXTENTS的所有扩展段。•更新表头块中的所有空闲表来反映出这一释放操作的结果。如果定义了多个空闲表组,更新对应于每个空闲表组的所有块。•重新设置位置标记•如果配置了多个进程(OPS环境),把段头和包含空闲表组的块写入磁盘中。使用DBMS_SPACE.UNUSED_SPACE可以识别段是否可以释放未使用块在内存中固定经常使用的对象,包括表等如果我们要固定表,那么可以在创立表的时候或者修改表属性时使用CACHE关键字,将表放置到BufferCache的LRU列表的MRU端。通常我们需要对于较小的但是频繁使用的表进行这种操作。ALTERTABLETABLE_NAMECACHE;我们也可以将需要频繁使用的表放置到另外一个独立的BufferCache中,比方KEEP池。这种操作可以使这些表的数据不至于很快被去除出DefaultBufferCache。ALTERTABLE<tablename>STORAGE(BUFFER_POOLKEEP);ALTERINDEX<indexname>

STORAGE(BUFFER_POOLKEEP);Freelist一个freelist同一个时刻只有有一个trans使用,但没有说这些trans不能交替使用(比方2个DML分别插入100blocks,但两个dml之间在分配各自的blocks的时候是交替进行的而不是串行的),也不必等别的trans或者别的DML用完之后才能用,正因为有一个交替的过程才会造成等待previouslyfreedblocks:这个应该指的是当session在做事务的时候可能释放block,这些释放的block就处于txfreelist上,这个txfreelist上的block是可以被进程自己使用的,也就是说previouslyfreedblocks就是进程自己释放的block。当一定时间之后(目前不详时机是如何触发的),这些previouslyfreedblocks会被释放回MFL。所以当进程在txfreelist上找不着(也就是没有previouslyfreedblocks),然后就去寻找processfreelist(也就是根据进程号算出来的freelist),如果还没有,那就从MFL去分配,如果MFL还没有,那就移动HWM假设freelists=10,则实际还存在一个masterfreelist,当HWM移动的时候会移动(10+1)*5(or_bump_highwater_mark_count)个块,但这些块不是直接挂在processfreelist上,更不是transectionfreelist,而是放在masterfreelist上,这样这些块对于所有transection和processfreelist都是可使用的,因为大家都会在transectionfreelist找不到的时候自己的processfreelist,然后找masterfreelist的,只是不能找别的processfreelist而已。关于死块,是这样的:当oracle在freelist中搜索5(_release_insert_threshold:default5)个block当发现每个block都不能装下一个行的时候(因pctused过高删除回收等原因),就直接移动HWm以获取新行,这是合理的。这样,有可能存在这样的现象,这个所谓的死块,总是大量的影响,会可能很频繁地被这么搜索5次然后扩展HWM,所以我们一定要小心指定pctused.当然pctused本身也可能大量影响IO(假设频繁删除的话)总结一下:如果我们定义了storage(freelists4freelistgroups2),那么在segmentheaderblock中有1个SuperMasterFreelist,有2个freelistblock,每个freelistblock中又有1个masterfreelist和4个processfreelist,当DML操作产生将本来不是free的block重新标志为空闲时,动态产生一个transactionfreelist。所有的freelistrecord中都只记录flag,listheaderblockdba和listtailblockdba,整个freelist是由存在于每个位于列表中的blockheader中指向下一个freeblock地址的指针这样类似链表的结构来完成的。1。session需要空间了,先在自己的TXFreelist上找,这是在找previouslyfreedblocks2。找不到,找Processfreelist3。再找不到,找mainfreelist4。再找不到,就是这一步,返回去找其它的TXfreelist,看看有没有commit了的,如果有,merge到mainfreelist上(这个时候其它事务的freeblock就能被这个事务使用了),然后移动最多5个block到自己的processfreelist上,开始使用5。所有的TXfreelist(是所有的还是找一个定值的数量,这个还需要验证,因为如果有非常多的transaction,是找完所有的效率高还是到了某个地步找不到干脆直接分配新的extent效率高)上都没有已经commit的事务,那么此时才移动HWM所以,照这样的步骤,同意你的看法,多个freelist不会造成实际上的空间浪费,只有多个freelistgroup时候才会有浪费。uncommitedTFL是指本session还没有提交的临时存在的TFL(私有的)PFL是为本进程选择的freelistprocessfreelist

然后是MFL(设置了freelist>1则存在一个MFL)mainfreelist如果是搜索空闲空间,是先搜索uncommitTFl>PFL>MFL(这时可能回收TFLs中block进MFL)>移动HWM行一行包括两局部:行头以及与行中的列相关的实际数据。链接的行和非链接的行都如此。对于非链接的行,将是一整行;而对于链接的行,它是行的一局部。行头至少用3个字节包含指向行的元数据,如所有行段的ROWID(如果行已经是分链/迁移的),物理地存在于这一行局部或整行中,以及集群关键字(如果表是集群的一局部)。实际的数据局部包含列头和列数据的长度。注意,一列(如LONGRAW)可能在于多个块。因此,可以用列头来识别每块中列数据的大小。这对别的变化的列数据类型也有用,如VARCHAR、VARCHAR2和RAW,可用来识别块中实际包含了多少列数据。对于固定长度的列,列头所指向的长度也是固定的(如DATA列有7个字节)。对于最多包含250个字节的列使用1个字节而对于更大的列(超过250个字节)使用3个字节。小于250个字节的可变长度的列有1个字节的头。然而,如果该列更新后体积变大,列头要扩展为3个字节。如果因为自由空间有限而使这一扩展无法进行,那么把该行迁移。如果列包含一个NULL(没有任何值)而且它物理地放NULL或NOTNULL(它们实际上有值)之前,那么前面NULL列的列头用0作为数据大小。另外,如果一个包含NULL值的列物理地放在行的末尾,那么即使是列头也不能由Oracle维护。这是因为开始新的一行说明当前行已经结束了而所有没有提供的列中的值都为NULL。因此,在NULL列之前声明所有必要的列(非空的)有助于优化数据库中中间的使用操作。列通常以声明的数据保存,除非在某些情况下,如当表中包含一个LONG/LONGRAW列时,在这种情况下,后者通常保存在最后。同样,如果修改表使其包含一个新的列,则最新的列保存在最后。行链接:产生在第一次插入数据的时候如果一个block不能存放一行记录的情况下。这种情况下,Oracle将使用链接一个或者多个在这个段中保存的block存储这一行记录,行链接比较容易发生在比较大的行上,例如行上有LONG、LONGRAW、LOB等数据类型的字段,这种时候行链接是不可防止的会产生的。行迁移:当一行记录初始插入的时候事可以存储在一个block中的,由于更新操作导致行长增加了,而block的自由空间已经完全满了,这个时候就产生了行迁移。在这种情况下,Ora

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论