第七章重做redo和撤消Undo是Oracle的重要特性用以保证事_第1页
第七章重做redo和撤消Undo是Oracle的重要特性用以保证事_第2页
第七章重做redo和撤消Undo是Oracle的重要特性用以保证事_第3页
第七章重做redo和撤消Undo是Oracle的重要特性用以保证事_第4页
第七章重做redo和撤消Undo是Oracle的重要特性用以保证事_第5页
已阅读5页,还剩62页未读 继续免费阅读

下载本文档

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

文档简介

7重做(redo)和撤消(Undo)是Oracle的重要特性,用以保证事务的可恢复性和可回退性。本章对Oracle的重做机制进行说明。RedoOracle通过redo来保证数据库的事务可以被重演,从而使得在故障之后,数据可以被恢复。Redo对于Oracle数据库来说至关重要。在数据库中,Redo的功能主要通过三个组件来实现:RedoLogBuffer、LGWR进程和RedoLogFile在归档模式下,RedoLogFile最终会经由 图7-1是Oracle的数据库实例示意图,RedoLogBuffer以及LGWR进程在图中皆有体现:7-RedoLogBuffer位于SGA之中,是一块循环使用的内存区域。其中保存数据库变更的相关信息。这些信息以重做条目(RedoEntries)形式(RedoEntries也经常被称为Redorecords。RedoEntries包含重构、重做数据库变更的重要信息,这些变更包括INSERT,UPDATE,DELETE,CREATE,ALTER或者DROP等。在必要的时候RedoEntries被用RedoEntries的内容被Oracle数据库进程从用户的内存空(PGA到SGA中的LogBuffer之中。RedoEntries在内存中占用连续的顺序空间,由于RedoLogBuffer是循环使用的,Oracle通过一个进程LGWR不断的把RedoLogBuffer的内容写出到RedoLogFile中,RedoLogFile同样是循环使用的。图7-2RedoLogBufferLGWR以及RedoLogFile7-Redo通过前面的章节,我们已经知道,用户数据通常在BufferCache中修改,Oracle通过高速缓存来提高数据操作的性能。当用户在ufferache中修改数据时,Oracle并不会立即将变更数据写出到数据文件上,因为独立的离散写出效率会很低。到目前为止,计算机系统中最容易出现瓶颈的仍然是磁盘的I/OOracle这样做的目的是为了减少IO的压力,当修改过的数据达到一定数量之后,可以进行高效地批量写出。大部分传统数据库(当然包括Oracle在处理数据修改时都遵循 mit策略。也Oracle引入了Redo机制,通过连续的、顺序的日志条目的写出将随机的、分散的数据块的写出SQL>selectgroup#,members,statusfrom MEMBERSRedoLogBuffer类似,SQL>selectgroup#,members,statusfrom MEMBERS11111LogSwitchLogSwitchDBWR进程将写满的日志文件保护的变更数据写回到数由于Redo机制对于数据的保护,当数据库发生故障时,Oracle就可以通过Redo重演进如果的redo过多,那么必然导致恢复的时间过长,在生产环境中,需保证恢 回顾一下我们在第一章中所提到的:检查点只是一个数据库,它存在的根本意义在于减少恢复时间。当检查点发生时(SCNCheckpointSCN)OracleDBWR进程,把修CheckpointSCN之前的脏数据(DirtyBuffer)BufferCache写入磁盘,在检查点完成后CKPT进程会相应的更新控制文件和数据文件头,记录检查点信息,标如果数据库运行在归档模式(所有生产数据库,都建议运行在归档模式,日志文件在重Redo与在一个多用户的并发系统中,大量用户进程都需要向RedoLogBuffer写入重做数据,Oracle通过Latch来保护和协调RedoLogBuffer的工作。同Redo相关的Latch主要有RedoCopyLatch、RedoAllocationLatch等,RedoAllocationLatch用于管理LogBuffer内存空间的分配,RedoCopyLatchRedoRedoLogBuffer过程的保护。一个进程在修改数据时产生Redo,Redo首先在PGA中保存,当进程需要将Redo信息CopyRedoLogBufferredocopylatchlatchredo拷贝到LogBuffer中。Redocopylatchredologbuffer中,在此过程中,LGWR应该等待直到进程拷贝完成才能把目标LogbufferBlock写入磁盘。初始化参数_LOG_SIMULTANEOUS_COPIES,定义允许同时写redo的redocopylatch的数量。在Oracle7和Oracle8里,_LOG_SIMULTANEOUS_COPIES缺省的等于CPU的数量。_log_simultaneous_copies8numberofsimultaneouscopiesintoredobuffer(#of_log_simultaneous_copies8numberofsimultaneouscopiesintoredobuffer(#ofcopySQL>Entervalueforpar: VALUESQL>select2fromv$latchwhereSQL>select2fromv$latchwherename='redo GETSIMMEDIATE_GETSIMMEDIATE_MISSESredo0redocopylatchLatchv$latch_childrenSQL>select2fromv$latch_childrenwherename='redo CHILD# GETSIMMEDIATE_GETS1redo6redoC7redo008redo008rowsRedocopylatch获取以后,进程紧接着需要redoallocationlatch,分配redo空间,空间分配完成以后,redoallocationlatchPGAredoCOPY入redologbuffer,COPY完成以后,redocopylatch释放。SQL>colnameforSQL>select2fromv$latchwherename='redo LATCH# MISSESIMMEDIATE_GETSredocopyLGWR去执行写出(redocopycommit等因素触发的SQL>colnameforSQL>select2fromv$latchwherename='redo LATCH# MISSESIMMEDIATE_GETS 113redo redowritinglatch竞争过多,Statspack可以获得这些信息,具体参考"logfilesync"等待一节在执行redocopy的过程中,进程以logfilesync处于等待。当进程从logfilesync中redoallocationlatch检查是否相应的redo已经被写入redologfile,如果尚未写入,进程必须继续等待。这是一个大致简化的Latch处理过程,用以说明Latch的处理机制。RedoLatchredoallocationlatchRedoLogBuffer写入Redo信息时需要获得此Latch,分配RedoLogBuffer空间。所以,如果对于一个繁忙的Latch通常也是竞争激烈的LatchRedoallocationlatch和RedoCopyLatch同属Top5请求的Latch之一: IMMEDIATE_MISSEScachebufferslrucachebuffersredo0redoallocationcheckpointqueueOracle9i Oracle9iR2中,OracleLOG_PARALLELISMOracleredoallocation的并发级别。如果定义LOG_PARALLELISM大于1,那么数据库将分配多个共享的RedoLogBufferBufferRedoAllocationLatchRedo的并发RedoLogBufferRedoLogBuffer的子池,与SharedPoolSubpool原理类似。多RedoLogBuffer机制又被称为PublicRedologStrands。图7-3是新机制下RedoLogBuffer原理示意图:7-如果你使用的是高端服务器,有超过16个处理器,并且经历非常高的redoallocationlatchredoredo生成能够增加更新密集型数据库的吞吐量,可以通过V$LATCH视图观察redoallocationlatch竞争的累计等待时间。SELECTsubstr(,1,20),gets,SELECTsubstr(,1,20),gets,misses,immediate_gets,immediate_missesFROMv$latchl,v$latchnameln in('redoallocation','redocopy')andln.latch#=如果MISSES对GETS比率超过1,或者IMMEDIATE_MISSES对+IMMEDIATE_MISSES)比率超过1%Latch16~64CPU时,OracleLOG_PARALLELISM2~8之间。你可以从低值(例如2)开始,以1redoallocationlatch竞争不再激烈,这个参数的设置可以提高应用的性能。大于8的LOG_PARALLELISM设置通常不被推荐。Oracle9iR2SQL>showparameter 1RedoAllocationLatchSQL>select*fromv$versionwhererownum<2;Oracle9iEnterpriseEditionRelease.0-SQL>select2fromv$latch_childrenwherename='redo CHILD# GETSIMMEDIATE_GETS1redo00在Oracle10gR2Oracle10g 在Oracle0g中,log_parallelism参数变为隐含参数,并且Oracle引入了另外两个参数,允许log_parallelism进行动态调整。缺省的_log_parallelism_dynamic参数被设置为True,如果SQL>Entervalueforpar:_log_parallelism_max被设置为不同于SQL>Entervalueforpar:old6:ANDx.ksppinmLIKEnew6:ANDx.ksppinmLIKE12NumberoflogbufferumnumberoflogbufferstrandsEnabledynamicstrands但是需要注意的是当日志并行度被设置大于 ORA-01374:_log_parallelism_maxORA-01374:_log_parallelism_maxgreaterthan1notsupportedinthisCause:LogMinerdoesnotmineredorecordsgeneratedwithlog_parallelismsettoavaluegreaterthan1Action:Oracle9iPublicRedologStrandsPBRSOracle10gR2PrivateRedologStrands的概念(缩写为PVRS,在PVRS机制下,数据库可以在共享池中分配大量的小的私有内存,通常每个大小在64~128K左右,被独立的RedoAllocationLatch所保护,当数据库中特定类型的小事务开始时会被绑定到独立且空闲PVRS,每个Buffer绑定一个活动事务。在新的机制下,Redo产生后可以直接存入PVRS,而不再保存在PGA中,这样就不再需要额外的内存拷贝过程,RedoCopyLatch也就不再需要(PVRS也因此被称为ZERO-COPYRedo而RedoCopy正是RedoAllocationLatch竞争的根源。7-4RedoLogBuffer7-Redo写出工作时,LGWRPBRSPVRS中的RedoFlushPublicRedoAllocationLatchPublicStrands的RedoCopyLatch需要被检查,所有包含活动事务的PrivateStrands需要被持有。PVRS在共享池中的内存分配信息(注意在RAC环境中不适用PVRS:SQL>selectbannerfromx$versionwhereindxin(0,3);OracleDatabase10gEnterpriseEditionRelease.0-ProdTNSforLinux:Version.0-ProductionSQL>select*fromv$sgastatwherename='privatestrands'; sharedprivateOracle10gR2中,OracleRedoAllocationLatchSQL>select2fromv$latch_childrenwherename='redo LATCH#CHILD# GETSIMMEDIATE_GETS12300400500600700800900000000000000000000000020以下是与PVRS相关的几个隐含参数,缺省的_log_private_parallelism被设置为SQL>Entervalueforpar: VALUE FALSENumberSQL>Entervalueforpar: VALUE_log_private_parallelism_mul

ActivesessionsmultipliertodeducenumberofprivatePrivatestrandmultiplierforlogspacePRVSV$SYSSTATIMU(InMemoryUndo)与PRVS紧密相关,所以两者的信息具有相关性(IMU在下一章中介绍:SQL>selectname,valuefromv$sysstatwhereupper(name)likedoublingupwithimu0IMUIMUIMUIMUrecursive-transaction9IMUundoretention0IMUktichg0IMUbind0IMUmbu0IMUpoolnotIMUCRIMUundoallocationIMURedoallocationIMU-failedtogetaprivateOSumresidentset0MonSep2613:29:25Private_strands3atlogswitchThread1advancedtologsequenceMonSep2613:29:25Private_strands3atlogswitchThread1advancedtologsequence58Currentlog#3seq#58mem#0:Currentlog#3seq#58mem#1:/u01/oradata/onlinelog/o1_mf_3_1m7lp0rp_.logThread1cannotallocatenewlog,sequence59CheckpointnotCurrentlog#3seq#58mem#0:Currentlog#3seq#58mem#1: PrivatestrandflushnotcompleteRedoLogFriFriMay1912:47:29Thread1cannotallocatenewlog,sequencePrivatestrandflushnotcompletCurrentlog#7seq#18357mem#0:/u03/oradata/bitst/redo07.logThread1advancedtologsequence18358Currentlog#8seq#18358mem#0:通过V$EVENT_NAMESQL>selectnamefromv$event_namewherelogfileswitch(privatestrandRedo大家知道,OracleRedoRedoLogFile可以连续、顺序的快速写出,另外一个方面也和Redo记录的精简内容有关。为了了解Redo改变向量(Change改变向量表示对数据库内某一个数据块所做的一次变更。改变向量(hangeector)中包含了变更的数据块的版本号、事务操作代码、变更从属数据块的地址(DBA)以及更新后的数据。例如一个Update事务包含一系列的改变向量,对于数据块的修改是一个向量,对于重做记录(Redo 例如一个Update的重做记录包括相应的回滚段的改变向量和相应的数据块的改变向下面以一个更新(Update)操作为例介绍一下这个过程,如图7-5

7-UPDATEempSETsal=4000Whereempno= 检查empno=7788记录在BufferCache中是否存在,如果不存在则到BufferCache中在回滚表空间的相应回滚段事务表上分配事务槽,这个操作需要记录Redo从回滚段读入或者在BufferCache中创建sal=3000的前镜像,这需要产生RedoLogSal=4000updateRedoLogBufferRedoLogBuffer记录提交信息,并在回滚段标记该事务为非(inactiveswitchlogfile使用sysSQL>altersystemswitch Systemaltered.SQL>select*from 11126-MAR-21119-MAR-31126-MAR-4119-MAR-*fromempwhere YST19-APR-SQL>updateempsetsal=4000where1rowSQL>CommitSQL>selectsid,serial#,usernameSQL>selectsid,serial#,usernamefrom2whereusername='SCOTT'; SERIAL#USERNAME405sysSessionSQL>SQL>ALTERSYSTEMDUMPLOGFILESystemaltered. Trace从日志文件的转储信息中,我们可以很容易的找到这个事务(sid=15,serial#=43870)的信REDORECORD-Thread:1RBA:.0010LEN:0x0198VLD:SCN:REDORECORD-Thread:1RBA:.0010LEN:0x0198VLD:SCN: :103/26/2006CHANGE#1TYP:0CLS:19AFN:2DBA:ktudhredo:slt:0x001dsqn:SCN:0x0819.0036f03cSEQ:1:0x0012siz:108fbi: uba:0x008000c3.04b1.0 pxid: 5:[ c21f记录的就是对于COL5的修改CHANGECHANGE#2TYP:0CLS:20AFN:2DBA:0x008000c3SCN:0x0819.0036f03bSEQ:1ktudbredo:siz:108spc:6740 :0x0012seq:0x04b1rec:0x0cxid:0x0002.01d.000038eaktublredo:slt:29rci:0opc:11.1objn:7961objd:7961tsn:Undotype:RegularTempObject:NoTablespaceUndo:NoBeginLastbuffersplit:prevctluba:prevctlmaxcmtscn:0x0819.00364c81prevtxcmtscn:KDOundoKTBop:0x03ver:0x01op:ZKDOOpcode:URProwdependenciesDisabledxtype:XAbdba:0x00405c5ahdba:0x00405c59itli:2ispac:0maxfr:tabn:0slot:7(0x7)flag:0x2clock:0ckix:0ncol:8nnew:1size:0 5:[ c23000(c21fCHANGE#3TYP:2CLS:1AFN:1DBA:0x00405c5aSCN:0x0819.0036efb1SEQ:1KTBop:0x11ver:op:Fxid:CHANGE#3TYP:2CLS:1AFN:1DBA:0x00405c5aSCN:0x0819.0036efb1SEQ:1KTBop:0x11ver:op:Fxid: uba:Blockcleanoutrecord,scn:0x0819.0036f14dver:0x01opt:0x02,entriesfollow...itli:1 :2scn:0x0819.0036efb1KDOOpcode:URProwdependenciesDisabledxtype:XAbdba:0x00405c5ahdba:0x00405c59itli:2ispac:0maxfr:tabn:0slot:7(0x7)flag:0x2clock:2ckix:0ncol:8nnew:1size:0 5:[ c2CHANGE#4MEDIARECOVERYMARKER SEQ:0当事务提交之后,记录的SCN信息,注CHANGE#4MEDIARECOVERYMARKER SEQ:0sessionsessionnumber =13serialnumber =405transactionnamesessionnumber =13serialnumber =405transactionname从以上的分析中可以看到,对于数据块的修改,如果执行写出,那么通常需要写出8K的Block,而对于Redo日志来说,重做信息却相当精简,Oracle只需要记录那些重构事务必须的操作代码(OP在以上的改变向量分析中,存在一个重要的操作代码(OP=OperationCode),该代码标志了操作的类型.下表列出了不同代码代表的操作级别,进一步的,操作级别和具体编号联合就可以详细的标示一个Changeector的操作:DML事务,Level11,相应的操作代码如下表所示对于前面的更新示范,OP11.5.UNDO的操作,其代码如下表所示,5.1UNDOUNDOHeader的操作,5.2表示对于回滚段头的更新操作在某库系统中,遇到一则数据被篡改的案例.某用户账户余额为0 改为40000元.这一篡改说明数据库存在极大的安全隐患,如果不找和消除这一隐患,则 7.5-7.6日9:00,balance字段被修改为40000。客户于7.6日上午11:00将此值重置为SQL>selectrowidfrom"CINMS"."BROAD_SUBSCRB"whereSQL>selectrowidfrom"CINMS"."BROAD_SUBSCRB"whereSQL>selectget_rowid('AAAQXKAAvAAAB2wAAn')SQL>selectget_rowid('AAAQXKAAvAAAB2wAAn')fromObject#Relative_fnoisBlocknumberis:7600Rownumberis createor cefunction(l_rowidinvarchar2)returnvarchar2ls_my_rowidcreateor cefunction(l_rowidinvarchar2)returnvarchar2ls_my_rowidvarchar2(200);rowid_typenumber;object_numbernumber;relative_fnonumber;block_numbernumber;row_numbernumber;ls_my_rowid:='Object#is 'Relative_fnois:'||to_char(relative_fno)||chr(10)||'Blocknumberis:'||to_char(block_number)||chr(10)||'Rownumberis returnls_my_rowid;/我们可疑看到,47Block7600上.Logminer解析日 PL/SQLproceduresuccessfully+PL/SQLproceduresuccessfullySQL>selectcount(*)from解析完成之后,可疑通过v$logmnr_contents视图来查找相关的修改操作.在该日志中,解析SQL>selectcount(*)fromSQL>selectcount(*)SQL>selectcount(*)fromv$logmnr_contentswhere1BROAD_SUBSCRB表,SQL_REDO和SQL_UNDO信息不可用SQL>SQL>selectscn,seg_name,sql_redo,sql_undo,rs_idfromv$logmnr_contentswhere;SCN -­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-­­-- UnsupportedSQL>selectfromv$logmnr_contents SESSION# 90Unsupported 根据session#,可以将这个会话的所有操作查询出来,注意第一条信息的绝对文件号是2,也就是UNDO表空间,说明该条目记录的是事务相关信息;第二条信息记录的是对于绝对文件号47块号7602号的操作:266237662372011-07-052011-07-05 66237根据前面查询到的scn等信息,可以再次搜索,获取用户的连接信息等,根据这些连接信息,SQL>selectsession_infofromv$logmnr_contentswherescn= login_username=CINMS_info=OS_username=AdministratorMachine_name=WORKGROUP\ANYlogin_username=CINMS_info=OS_username=AdministratorMachine_name=WORKGROUP\ANY我们可以将日志文件转储出来,然后根据查询到的RS_ID(RS_ID记录的是REDORecordSET的ID号,REDO中的REDO记录条目,实际上也就是RBA信息)去搜索,找到相关的UNDO信息,转出日志可以用类似如下命令:altersystemdumplogfile根据前面的查询相关的事务和修改信息的RS_ID分别为:0x00309e.00028a0a.0010在文件中可以找到如下第一个RS_ID详细的REDO信息,这是事务开始之前,对UNDO的修改和锁定REDORECORD-Thread:1RBA:0x00309e.00028a0a.0010LEN:0x01a4VLD:>>>>RBASCN: :107/05/2011CHANGE#1TYP:0CLS:21AFN:2 SCN:0x0001.4be86ed9SEQ:1>>>>OP:52这是UNDOHeaderktudhredo:slt:0x0022sqn:0x c:0x0012siz:108fbi:0uba:0x pxid:0x0000.000.CHANGE#2TYP:0CLS:22AFN:2 SCN:0x0001.4be86ed8SEQ:1OP51这是UNDOBLOCKUNDOHEADER的修ktudbredo:siz:108spc:7640:0x0012seq:0xaf17rec:0x04xid:0x0003.022. ktublredo:slt:34rci:0opc:11.1objn:66237objd:67018tsn:8Undotype:Regularundo Begintrans Lastbuffersplit:NoTempObject:NoTablespaceUndo: prevctluba: prevctlmaxcmtscn:0x0001.4be86985prevtxcmtscn:0x0001.4be869b3KDOundorecord:KTBop:op:0x04ver:op:Litl:xid:0x0005.023.0019a945uba::C--- lkc:0 scn:0x0001.4be11d6cKDOOpcode:LKRrowdependenciesDisabledxtype:XAbdba:0x0bc01db0hdba:0x0900e509itli:2ispac:0maxfr:4863tabn:0slot:39to:CHANGE#3TYP:2CLS:1AFN:47DBA:0x0bc01db0SCN:0x0001.4be21203SEQ:1>>>>OP114是锁定行实际上也就是锁定KTBop:0x01ver:op:Fxid:0x0003.022. uba:0x KDOOpcode:LKRrowdependenciesDisabledxtype:XAbdba:0x0bc01db0hdba:0x0900e509itli:2ispac:0maxfr:4863tabn:0slot:39to:CHANGE#4MEDIARECOVERYMARKER SEQ:0sessionnumber =90serialnumber =14480currentusername=CINMS username= MachineOS==OSprocess =OSprogramname=transactionname=REDORECORD-Thread:1REDORECORD-Thread:1RBA:0x00309e.00028b4d.0010LEN:0x0114VLD:>>>>RBA,也即SCN: :107/05/2011CHANGE#1TYP:0CLS:22AFN:2 SCN:0x0001.4be86efeSEQ:1>>>>OP51这里记录的是前镜像数据ktudbredo:siz:116spc:7530 :0x0022seq:0xaf17rec:0x05xid:0x0003.022. ktuburedo:slt:34rci:4opc:11.1objn:66237objd:67018tsn:Undotype:Regular Undotype:Lastbuffersplit:TablespaceTablespaceUndo:KDOundoKTBop:0x04ver:op:Litl:xid:0x000a.01e.001a0c96uba::C--- lkc:0 scn:0x0001.4bb7744aKDOOpcode:URProwdependenciesDisabledxtype:XAbdba:0x0bc01db2hdba:0x0900e509itli:3ispac:0maxfr:4863tabn:0slot:47(0x2f)flag:0x0clock:0ckix:0ncol:33nnew:2size:-1col7:[1]col15:[1]>>>>这里记录了修改前的值分别修改了第7和第15列信息(0编号,等于第816列80就是十进制的CHANGE#2TYP:2CLS:1AFN:47DBA:0x0bc01db2SCN:0x0001.4be1efdbSEQ:1>>>>OP115指更新行记录信息KTBop:0x01ver:op:Fxid:0x0003.022. uba:0x KDOOpcode:URProwdependenciesDisabledxtype:XAbdba:0x0bc01db2hdba:0x0900e509itli:3ispac:0maxfr:4863tabn:0slot:47(0x2f)flag:0x0clock:3ckix:0ncol:33nnew:2size:1col7:[1]col15:[2]c3>>>>这里是更新后的值,c305SQL>selectfromv$logmnr_contentswheresession#=90andseg_name='BROAD_SUBSCRB'; ABS_FILE#REL_FILE#DATA_BLK#DATA_OBJ#RS_ID2011-07-2011-07-2通过对日志的详细分析,发现了机器名为ANY的机器于7月5日下午登陆服务器0--‐0--‐JU-- Files\PLSQLDeveloper\plsqldev.exe)(HOST=ANY)(USER=Administrator)))*(ADDRESS=(PROTOCOL=tcp)(HOST=65)(PORT=1940))*establish*cinms*0作为一个数据库从业人员,我们需要从中了解到:接触数据,意味着责任与义务,必须具备严格的职业道德操守,做数据的保护人而不是者.产生多少redo,那么不同的操作会产生多少Redo呢?SQL*plusautotrace当我们在SQL*plus中启用autotrace后,在执行了特定的DML语句时,Oracle会显示该语句的统计信息,其中,redosize一栏表示的就是该操作产生的Redo的数量,其单位为SQL>setautotracetraceSQL>insertinto2select*from28rows4consistent0physical776redov$mystatOraclev$mystatSessionSessionRedoSQL>colnameforSQL>select2fromv$statnamea,v$mystat3wherea.STATISTIC#=b.STATISTIC#='redoNAMEredo SQL>insertintoeygleselect*from56rowsSQL>selectfromv$statnamea,v$mystatwherea.STATISTIC#=b.STATISTIC#andNAMEVALUE=redoSQL>select57784-5654057784-v$sysstat对于数据库全局Redo的生成量,我们可以通过v$sysstatvaluefor99999999999999tname,valuev$sysstatwherename='redo从v$sysstat视图中得到的是自数据库实例启动以来的累积日志生成量,我们可以根据实SQL>altersessionsetnls_date_format='yyyy-mm-ddhh24:mi:ss';Sessionaltered.SQL>selectstartup_timefromv$instance;2005-08-25SQL>select(selectvalue/1024/1024/1024fromv$sysstatwherename='redo(selectround(sysdate-(selectstartup_timefromv$instance))fromdual)from如果数据库运行在归档模式下,由于其他因素的影响,以上Redo生成量并不代表归档日SQL> PLETION_TIME,BLOCKS*BLOCK_SIZE/1024/1024SQL> PLETION_TIME,BLOCKS*BLOCK_SIZE/1024/1024fromv$archived_logwhererownumandCOMPLETION_TIMEbetweentrunc(sysdate)-2andtrunc(sysdate)-1; COMPLETION_TIMEMB2006-05-0900:00:092006-05-0901:01:132006-05-0901:35:572006-05-0902:02:462006-05-0902:06:232006-05-0902:09:562006-05-0902:13:362006-05-0902:16:212006-05-0903:00:282006-05-0903:01:0310rowsSQL>SQL>selecttrunc(COMPLETION_TIME),sum(Mb)/1024DAY_GB234PLETION_TIME,BLOCKS*BLOCK_SIZE/1024/1024MbfromwhereCOMPLETION_TIMEbetweentrunc(sysdate)-2andtrunc(sysdate)-groupby5 09-MAY-06SQL> TRUNC(completion_time),SUM(mb)/1024FROM(SELECTNAME,completion_time,blocks*block_size/1024/1024FROMGROUPBYTRUNC(completion_time); 28-APR-29-APR-30-APR-01-MAY-02-MAY-03-MAY-04-MAY-05-MAY-0605-MAY-0606-MAY-0607-MAY-0608-MAY-0609-MAY-0610-MAY-0611-MAY-0614rows空间分配等问题。将这些数据导入Excel,可以很容易的获得直观的曲线图,进行辅助分析与报告(以下图表来自不同数据: 为了保证用户可以快速提交,LGWR的写出必须非常活跃,实际上也确实如此,我们非LGWR写触发条件就有:3秒钟超时LGWRrdbmsipcmessage3秒LGWRredoLGWR将执行写出操作,logfileparallelwrite等待将会出现WAITWAIT#0:nam='rdbmsipcmessage'WAIT#0:nam='rdbmsipcmessage'p1=300p2=0p1=300p2=0WAIT#0:nam='rdbmsipcmessage'ela=566819p1=300p2=0WAIT#0:nam='logfileparallelwrite'ela=115p1=1p2=2p3=1WAIT#0:nam='rdbmsipcmessage'ela=45752p1=213p2=0p3=0WAIT#0:nam='logfileparallelwrite'ela=94p1=1p2=3p3=1WAIT#0:nam='rdbmsipcmessage'ela=51762p1=208p2=0p3=0WAIT#0:nam='logfileparallelwrite'ela=91p1=1p2=1p3=1WAIT#0:nam='rdbmsipcmessage'ela=29033p1=200p2=0p3=0WAIT#0:nam='logfileparallelwrite'ela=99p1=1p2=2p3=1WAIT#0:nam='rdbmsipcmessage'ela=40293p1=197p2=0p3=0WAIT#0:nam='logfileparallelwrite'ela=87p1=1p2=1启用,从 我们在各种文档上经常会看到的2RedoLogBuffer1/3RedoLogBuffer1M脏数(Process在logbuffer中分配和使用空间,已经使用的Logbuffer的数量将被计算。如果使用的块的数量大于或等于一个隐含参数_log_io_ize的设置,那么将会触发LWR写操作。如果此时LGWR未处于活动状态,那么LGWR将被通知去执行写操作缺省的_log_io_size1/3logbuffer1MX$KSPPSV中显示的0值,意为缺省值。X$KSPPSVX$KSPPSV的含义为:[K]ernel[S]ervice[P]arameterComponent[S]ystem[也就是,LGWR将在Min(1M,1/3logbuffersize)时触发。注意此logbuffersize是logblockSQL>@D:\GetHiddenParameter.sqlEntervalueforpar:log_ioold14: x.ksppinmlike'%_&par%'new14: x.ksppinmlike'%_log_io%' 0LogBuffer3MRedoLogBuffer时,以上2个条件可能同时达到,从而可以在某种程度上避免LGWR当一个事物提交时,在redostream在这些redo被写到磁盘上之前,这个事物是不可恢复的。所以,在事务返回成功标志给用户前,必须等待LGWR写完成。进程通知LGWR写,并且以logfilesync开始休眠,1秒。Oracle的隐含参数_wait_for_syncfalseredofilesync的等待,但是就SQL>@D:\GetHiddenParameter.sqlEntervalueforpar:wait_for 注意,在递归调用(recurivecall)中的提交(比如过程中的提交)不需要同步redo直到需要返Comt操作的B。SGAredologblocknumber。如果多个提交在唤LGWRlogblocknumberredo都将被写入磁盘。这有时候被称为组提交(groupcommit).DBWn如果DBWR将要写出的数据的HighRBA超过LGWR的On-DiskRBA,DBWR将通知LGWR(Recovery时将无法恢复Oracle8iDBWR将等待logfilesync;从Oracle8i开始,DBWR把这些Block放入一个延迟队列,同时通知LGWR执行redo写出,DBWR可以继续执行无需等待的数据写出。在生产环境中,通常用户提交的频率是很高的,下面是来自Statspackperperredoblocksredobufferallocation4redoredologspace4redologspacewait8redoredosynchredosynchredoredowriteredowriterredouserusercommits23.注意到这个数据库中,平均每秒用户就提交了23.3RedoLog RedoLogBufferLOG_BUFFER定义。该参数的缺省值:Max(512KB,128KB*CPU_COUNT)通常这一缺省值是足够的,从上一节我们可以知道,RedoLogBuffer的写出操作是相当频繁的,所以过大的LogBuffer设置通常是没有必要的;如果缺省值不能满足要求,根据我们前面的介绍,一般来说3M是一个较为合理的调整开端。Log_buffer参数的设置是否需要调整,可以从数据库的等待SQL>selectevent#,namefromv$event_namewherename='logbufferspace';EVENT#NAME logbufferLogBufferSpace等待出现并且较为显著时,我们可以考虑增大LogBuffer以缩减SQL>select*fromv$versionwhererownum<2;OracleDatabase10gEnterpriseEditionRelease.0-ProdSQL>showparameterlog_buffer SQL>select*from2wherenamein('FixedSGASize','RedoBuffers','GranuleSQL>select*fromv$versionwhererownum<2;OracleDatabase10gEnterpriseEditionRelease.0-ProdSQL>showparameterlog_buffer SQL>select*from2wherenamein('FixedSGASize','RedoBuffers','GranuleSize');BYTESRESFixedSGAfromRedoGranuleSQL>select SQL>insertintotSQL>insertintotselect*from26rowscreated.SQL>commit;Commitcomplete.提交完成,这个提示意味着Oracle已经将此时间点之前的redo写入了重做日志文件中,这个日志写完成之后,Oracle可以释放用户去执行其他任务。如果此后发生数据库,那么Oracle可以从重做日志文件中恢复这些提交过的数据,从而保证提交成功的数据不会丢失。那么我们应该记住的Oracle的一个原则是:确保提交成功的数据不丢失。这个保证正是通过redoOracleOracle允许对重做日志文件进行镜像。从Oracle10g开始,如果设置了闪回恢复区,则Oracle缺省的就会对日志文件进行镜像,SQL>*from 112233镜像的好处是当某一个日志出现问题,另外一个日志仍然可用,可以保证数据不丢失,而且通常镜像于不同的硬盘,当某个出现故障时,另外的可以用于保证镜像日志的安全。LogFileSync在Oracle数据库的等待中,经常可以看到Logfilesync处于显著的位置,类似以AWR报告信息显示,Logfilesync占据数据库55.1%的DB上一节提到Commit的流程,LogFileSync就是提交的体现之一,这个流程的主PostLGWR–>LGWRLogFileSync->LGWR->LGWR–>LGWR–>用户进程标记提通过操作系统的工具可以清晰的观察到这个流程以下是使用truss命令grid1 6270:03oracle1 6270:07以下重点框住的部分就是LGWR在写出时执行的一个操作流程(信息来自Solaris下的OracleDatabase11gR2:LWP代表轻量级进程(LightWeightprocess),指LWP。每一个进程有一个或多个LWPs,每个LWP由一个内核线程支持。 PARKUNPARKLWP进程进入等待,后者唤醒和重用之前的LWP进程.fcntl文件控制(filecontrol260为日志文件,260LGWRfd下,可以找到这个文件:solaris*orcl-/home/oracle$cd/proc/2104/fdsolaris*orcl-/proc/2104/fd$ls-l260 1 6月29日16:22strings800M234,solaris*orcl-/proc/2104/fd$strings260|moreThread0001, ,SCN0x000001b0191d-pwrite为执行写出,写日志文件,该函数为标准的系统调用,在指定文件特定偏移量开始写ssize_tpwrite(intfildes,constvoid*buf,size_tnbyte,off_toffset);512Bytes1接下来的写出以KernalAIOsemctl进行信号量置位,其中7号为Oracle数据库的信号量集,通过ipcs可以看到正是这一输出:LogFileSync等待,前后各包含一次semtimedop的信号量操作。LogFileSyncRAID10是最好的这个等待是累计值,也就是说,当仅有的一个LGWR执行写出时,可能有多个进程处1001LGWR100毫秒的等待,所以这个有时并不一定如显示的那样影响深重;可以通过V$LOGSQL>selectgroup#,status,first_change#GROUP#STATUS 1INACTIVE2CURRENT3INACTIVE4INACTIVECurrentACTIVE的日志是活动的非当前日志,该日志可能已经完成归档也可能没有归档,活Crash恢复时会被用到。FriNov1814:26:57Thread1cannotallocatenewlog,sequence7239CheckpointnotcompleteCurrentFriNov1814:26:57Thread1cannotallocatenewlog,sequence7239CheckpointnotcompleteCurrentlog#5seq#7238mem#0:sid,event,statefromv$session_wait;134687259pmonrdbmsipcmessagerdbmsipcmessagerdbmsipcmessagerdbmsipcmessagerdbmsipclogfileswitch(checkpointdbfileparallelwritesmontimerSQL*Netmessageplet WAITINGWAITEDKNOWNTIMEWAITEDKNOWN当这种问题出sid,event,statefromv$session_wait;134687259pmonrdbmsipcmessagerdbmsipcmessagerdbmsipcmessagerdbmsipcmessagerdbmsipclogfileswitch(checkpointdbfileparallelwritesmontimerSQL*Netmessageplet WAITINGWAITEDKNOWNTIMEWAITEDKNOWN10rowsselected. 同时注意到DBWR进程(sid=2)正在进行dbfileparallelwrite,日志文件必须等待DBWRSatMar1821:47:15ThreadSatMar1821:47:15Thread1advancedtologsequenceCurrentlog#4seq#292mem#0:/opt/oracle/oradata/conner/redo04.logThread1cannotallocatenewlog,sequence293CheckpointnotcompleteCurrentlog#4seq#292mem#0:SatMar1821:47:19CompletedcheckpointuptoRBA[0x123.2.10],SCN:0x0819.0032c424CompletedcheckpointuptoRBA[0x122.2.10],SCN:0x0819.0032c3eSatMar1821:47:20BeginninglogswitchcheckpointuptoRBA[0x125.2.10],SCN:Thread1advancedtologsequenceCurrentlog#2seq#293mem#0:SatMar18SatMar1821:47:12BeginninglogswitchcheckpointuptoRBA[0x122.2.10],SCN:0x0819.0032c3SatMar1821:47:12ARC0:MediarecoverydisabledSatMar1821:47:122006Thread1advancedtologsequenceCurrentlog#1seq#290mem#0:BeginninglogswitchcheckpointuptoRBA[0x123.2.10],SCN:0x0819.0032c424SatMar1821:47:13通过这些对比和观察,可以使我们更好的了解Oracle的运行机制。 plete日志文件所在磁盘I/OI/O瓶颈,DBWR Raid5等方式I/ODBWRI/O非活动日志,该日志在实例恢复时不再需要,但是在介质恢复时可能会用到。INACTI状态的日志也可能没有被归档。如果数据库启动在归档模式,在未完成归档之前,日志文件也不允许被覆盖,这时候,活动进程会处于logfileswitch(archivingneeded)等待之中。日志是否完成归档,可以根据 字段进行判断,以下案例日志文ARCHIVED状态为NO,也就是尚未归档SQL>archivelogDatabaselog ArchiveAutomatic Archivedestination Oldestonlinelogsequence Nextlogsequenceto Currentlog SQL>select*fromGROUP#THREAD# BYTESMEMBERSARCHIVED FIRST_CHANGE#11126-MAR-21119-MAR-31126-MAR-4119-MAR-SQL>selectsid,eventfromSIDDMLSQL>selectsid,eventfromSID11pmon2rdbmsipc3rdbmsipc6rdbmsipc7rdbmsipc10rdbmsipc4rdbmsipc5logfileswitch(archivingneeded)9logfileswitch(archivingneeded)13SQL*Netmessage10rowsSQL>connectORA-00257:archivererror.SQL>connectORA-00257:archivererror.Connectinternalonly,SunApr917:42:11Errorsinfile/opt/oracle/admin/conner/bdump/conner_arc0_4475.trc:ORA-16038:log4sequence#308cannotbearchivedORA-00354:corruptredologblockORA-00312:onlinelog4thread1:'/opt/oracle/oradata/conner/redo04.log'SunApr917:42:112006ARC1:Evaluatingarchive log4thread1sequence308ARC1:Beginningtoarchivelog4thread1sequence ARC1:Logcorruptionnearblock2change0timeARC1:AllArchivedestinationsmadeinactiveduetoerror这种情况通常是由数据库异常引起的,可能是因为I/O缓慢,也可能是因为事务量过大,在特殊情况下,有可能是因为日志损坏。对于本案例就属于后者,通常我们可以通过检查告警日志文件(alert_<id>.log)发现问题所在:注意到在以上日志中,数据库提示日志损坏(LogCorruption),这就需要DBA进行判断并进指该日志从未被写入,这类日志可能是刚被添加到数据库或者在RESETLOGS之后被重初始化参数LOG_BUFFER决定了RedoLogBufferLOG_BUFFER中的RedoEntriesbytesLGWRBlockredo写入磁盘,redoblocksize是Oracle源代码中固定的,与操作系统相关。SQL>selectmax(lebsz)from512bytesSQL>selectmax(lebsz)from也可以从v$sysstat中的统计信息中通过计算粗略得到,以下几个统计信息如:redosize redo信息的大小redowastageredoredoblockswritten--LGWRredoblockredoblockheader16bytesredoblockSQL>selectname,valuefrom wherenamein('redosize','redowastage','redoblocks blocksselectceil(16++63904)/4657)rbsizefrom[oracle@jumperconner]$dbfsizeredo01.[oracle@jumperconner]$dbfsizeredo01.loDatabasefile:redo01.logDatabasefiletype:fileDatabasefilesize:20480512byteblocks[oracle@jumperconner]$dbfsizesystem01.dbfDatabasefile:system01.dbfDatabasefiletype:fileDatabasefilesize:512008192byteblocks[oracle@jumperconner]$whichBlockSize512bytesBlock8192bytes当然,也可以通过转储日志文件的方式来获取日志文件块大小,转储日志文件头可以通过如下命令实现:ALTERSESSIONSETEVENTS'immediatetracenameredohdrlevel查查 文件可以得到类似如下信息,输出中的bsz就是指RedoBlogSize为512LOGFILE(name#3)Thread1redologlinks:forward:2backward:siz:0x5000seq:0x ehws:0x1bsz:512nab:0xffffffff :0x8dup:1Archivelinks:fwrd:0ba

温馨提示

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

评论

0/150

提交评论