相克军 ORACLE 讲座 深度剖析UNDO段 笔记.docx

上传人:b****6 文档编号:6291826 上传时间:2023-01-05 格式:DOCX 页数:19 大小:1.16MB
下载 相关 举报
相克军 ORACLE 讲座 深度剖析UNDO段 笔记.docx_第1页
第1页 / 共19页
相克军 ORACLE 讲座 深度剖析UNDO段 笔记.docx_第2页
第2页 / 共19页
相克军 ORACLE 讲座 深度剖析UNDO段 笔记.docx_第3页
第3页 / 共19页
相克军 ORACLE 讲座 深度剖析UNDO段 笔记.docx_第4页
第4页 / 共19页
相克军 ORACLE 讲座 深度剖析UNDO段 笔记.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

相克军 ORACLE 讲座 深度剖析UNDO段 笔记.docx

《相克军 ORACLE 讲座 深度剖析UNDO段 笔记.docx》由会员分享,可在线阅读,更多相关《相克军 ORACLE 讲座 深度剖析UNDO段 笔记.docx(19页珍藏版)》请在冰豆网上搜索。

相克军 ORACLE 讲座 深度剖析UNDO段 笔记.docx

相克军ORACLE讲座深度剖析UNDO段笔记

相克军ORACLE讲座深度剖析UNDO段笔记

 

UNDO表空间用来存放改变前的旧值。

里面也有段区块,ORACLE自动建立生成、自动使用UNDO段。

作为高级别的DBA是需要知道ORACLE如何使用UNDO段的。

1Undo表空间及管理方式

ORACLE开始一个事务的时候,会用到表空间。

将修改前的数据保存在UNDO段里。

Undo的三个作用

读的一致性,构造CR块

回滚

实例恢复(时的回滚)

--查询UNDO表空间的名字

SQL>showparameterundo_tablespace;

NAMETYPEVALUE

-----------------------------------------------------------------------------

undo_tablespacestringUNDOTBS1

--查询UNDO表空间的数据文件

SQL>selectfile_name,bytes/1024/1024fromdba_data_fileswheretablespace_namelike'%UNDOTBS1%'

FILE_NAME

BYTES/1024/1024

-----------------------------------------------------------------------------------------------

/opt/oracle/oradata/orcl/undotbs01.dbf275

--查询UNDO表空间的段

SQL>select*fromv$rollname;

USNNAME

----------------------------------------

0SYSTEM

1_SYSSMU1$

.........

10_SYSSMU10$

--查询其中='_SYSSMU1$'这个段的占有多个块多少个区

SQL>selectsegment_name,blocks,extentsfromdba_segmentswheresegment_name='_SYSSMU1$';

SEGMENT_NAMEBLOCKSEXTENTS

----------------------------------------------------------------------------------------------------

_SYSSMU1$193617

--查询'_SYSSMU1$'这个段分配区的具体情

SQL>selectsegment_name,tablespace_name,extent_id,file_id,block_id,blocksfromdba_extentswheresegment_name='_SYSSMU1$';

SEGMENT_NAMETABLESPACE_NAMEEXTENT_IDFILE_IDBLOCK_IDBLOCKS

------------------------------------------------------------------------------------------------------------------------------------------------------

_SYSSMU1$UNDOTBS10298

_SYSSMU1$UNDOTBS11288498

.........................................

_SYSSMU1$UNDOTBS1162905128

由上面这个结果,可以得出结果:

UNDO表空间中的段中的区中的块儿是连续的,但是区与区之不是连续的

showparameterundo;

NAMETYPEVALUE

-----------------------------------------------------------------------------

undo_managementstringAUTO

undo_retentioninteger900

undo_tablespacestringUNDOTBS1

showparameterundo;

NAMETYPEVALUE

-----------------------------------------------------------------------------

undo_managementstringAUTO

undo_retentioninteger900--ORACLE不希望已经提交的事务,对应的UNDO段中的区,立即就被覆盖,而设定这个参数undo_retention900表示事务已经提交之后,UNDO段中的区还可以在UNDO段中存活900秒,过期之后,才可以被覆盖

undo_tablespacestringUNDOTBS1

selectnamefromv$parameterwherenamelike'%undo%';

undo_management

undo_tablespace

undo_retention

altertablespaceundotbs1retentionguarantee;--表示undo_retention至少900秒以后,过期之后,才可以被覆盖

selecttablespace_name,retentionfromdba_tablespaces;--查询设置结果

altertablespaceundotbs1retentionnoguarantee;

selecttablespace_name,retentionfromdba_tablespaces;--查询设置结果

Undo段中区的状态

free空闲

expired过期:

超UNDO段中的区在提交之后,存活的时间超过了undo_retention900钞

inactive已经提交

active活动

ORACLE在自动使用Undo段中区时,先用“free”空间,实在不行,才用“expired”过期的空间。

如果空间还不够,用户“inactive”,如果还是空间不够,这时就要报错了。

进程就要挂起了。

ORACLE使用Undo段空间的顺序:

“free”空间--->“expired”过期的空间---->“inactive”空间---如果空间还不够---->报错

检查UNDOSegment状态

SELECTusn,xacts,rssize/1024/1024/1024,hwmsize/1024/1024/1024,shrinks

fromv$rollstatorderbyrssize;

显示UNDO

selectextent_id,bytes,statusfromdba_undo_extentswheresegment_name='_SYSSMU1$';

检查UNDOSegment状态

selecta.usn,a.xacts,a.rssize/1024/1024/1024,a.hwmsize/1024/1024/1024,a.shrinksfromv$rollstataorderbyrssize;

2、图解一个事务的操作流程

Undo段的组成,段头、回滚块

事务ID

selecta.xid,a.xidusn,a.xidslot,a.xidsqn,a.ubablk,a.ubafilfromv$transactiona;

XIDXIDUSNXIDSLOTXIDSQNUBABLKUBAFIL

------------------------------------------------------------------

090016004B050000922135510332

事务表:

undo段的第一数据块,每一个回滚段最多可以47个事务

回滚段的段头块

select*fromv$rollname;

selectheader_block,header_filefromdba_segmentswheresegment_name='_SYSSMU1$';

--将回滚段“_SYSSMU1$”这个段的段头块给dump文件:

altersystemdumpundoheader'_SYSSMU1$';//转储回滚段头

selectspidfromv$processwhereaddrin(selectpaddrfromv$sessionwheresid=(selectsidfromv$mystatwhererownum=1));

--查看UNDO段段头块的内容dump出来的信息

cd$ORACLE_BASE/admin/$ORACLE_SID/dump/

viorcl_ora_9051.trc

altersystemdumpdatafile5block4038;//转储回滚段数据块

事务槽:

一个事务修改一个数据块,一个数据块可能被多个事务修改。

在这个数据块的头部,有一个事务槽,可以写入1-255个事务。

开始一个事务,找到一个回滚段里找一到一个段,在它的控制槽里写上事务信息

在要修改的数据块的事务槽里写上事务信息。

此少要在两个位置写上事务信息:

1)回滚段的段头块里2)数据块的事务槽里。

UBA:

(undoblock)回滚块

要修改数据时,先将修改前的数据放到UNDO段里,叫回滚块

ORACLE事务处理的五大步骤:

第一件事:

一个事务开始,在UNDO表空间里找一个相对空闲的UNDO段,然后在这个UNDO段的段头块里边的事务表里,找到其中一个槽位,在事务表里的槽位里找一个行,

将自己的事务信息XID写上去。

同时在这个回滚段里给这个事务分配一个UNDO块,并且把这个UNDO块儿的地址写到事务表里去。

即在事务表里要写入两个地址:

xid(事务ID),uba(所分配的UNDO块儿的地址)

第二件事:

在修改数据块之前,首先找到这个要修改的数据块的头部,找到它的事务槽,在事务槽里找一行,把事务编号XID写上。

同时事务槽里与有个uba地址指向回滚块。

第三件事:

把要修改的五行信息写到UNDO块里(回滚块),并且把这个UNDO块儿的地址写到数据块里的事务槽里的uba地址。

第四件事:

接下来,还要修改其它信息,再分一个UNDO块,将新分配的uba地址记录到数据块的事务槽里。

第五件事:

事务表里的uba地址就指向了最新分配的UNDO块。

这样形成了两条链:

第一组链:

由数据块的事务槽的XID指向事务表的事务,同时,数据块的事务槽里的uba地址指向UNDO段里UNDO块的地址

作用:

利用这个链接,可以直接从数据块里找到回滚块,直接构造出CR块。

而不用通过事务表,找到回滚块。

疑问:

为什么事务ID,即XID同时存在两个地方:

事务表和数据块里?

为什么需要数据块儿的SID还要指向事务表里的事务ID。

 

第二组链:

事务表uba指向最新的回滚块,最新的回滚块能找到次新的回滚块,次新的回滚块能找到更新的回滚块,以此形成一条链。

作用:

事务表里的uba指向最新的回滚快。

使用最新的回滚块找到次新的回滚块,把次新的回滚块回滚了,这样依次往前回滚rollback。

总结:

一个事务开始以后ORACLE修改了1)事务段的段头块的事务表,2)UNDO块,3)数据块的事务槽,4)数据块本身

这四个被修改的地方都在数据块里。

所以全都会产生REDO。

所以REDO不仅仅记录数据的改变,而且记录了1)事务表的改变2)UNDO块的改变3)数据块事务槽的改变4)数据块的改变

5、读一致性

ORA-01555错误

6、undoadvisor

EM

7、事务槽ITL

默认是1

最大255(从ORACLE10G开始不能更改)

selectINI_TRANS,MAX_TRANSfromdba_tableswheretable_name='T2';

事务槽的争用

事务槽的争用:

如上图,当未提交的事务不断增多,而多A事务和B事务都同时在修改这同一个数据块,而且都没有提交,没有提交的事务,事务槽信息是不可以被告覆盖的,必须保留,随着事务的增多,在这个数据块的事务槽里的事务信息会不断的增多,当又有新的事务需要写进这个数据块的事务增时,已经没有空间了,那就这个新的事务就需要等待别的事务提交,只有别的事务提交之后,这个新事务才可以写进去。

这就叫“事务槽的争用”。

如何防止事务槽争用:

1)对于往一个表中多个事务同时插入数据,INSERT操作时,ORACLE给每个事务开启一个数据块。

这样就不会产生事务槽争用。

2)但对于UPDATE和DELETE操作是没有办法解的,所以UPDATE和DELETE操作容易发生事务槽争用。

事务等待及行级锁的形成:

createtablet10(idnumber(5),namechar(2000));

insertintot10values(1,'aa');

insertintot10values(2,'bb');

insertintot10values(3,'cc');

insertintot10values(4,'dd');

insertintot10values(5,'ee');

commit;

selectdbms_rowid.rowid_relative_fno(rowid)fno,dbms_rowid.rowid_block_number(rowid)block_number,id,namefromt10;

updatet10setname='abcd'whereid=1;

在DBA用户下:

selecta.ubafil,a.ubablk,a.xidusn,a.xidsqn,a.start_scnbfromv$transactiona;

selecta.ubafil,a.ubablk,a.xidusn,a.XIDSLOT,a.xidsqn,a.start_scnbfromv$transactiona;

select*fromv$rollname;

将回滚段_syssmu2$的段头块dump成文本,放在$ORACLE_BASE/admin/$ORACLE_SID/dump/目录下,

altersystemdumpundoheader'_SYSSMU2$';

altersystemdumpdatafile2block3657;

查询DUMP出来的文件,查当前会话编号

selectspidfromv$processwhereaddrin(selectpaddrfromv$sessionwheresid=(selectsidfromv$mystatwhererownum;

SPID

------------

9614

cd$ORACLE_BASE/admin/$ORACLE_SID/dump/

事务槽dump文件的内容:

还可以指文件号和块号DUMP出来:

selectdbms_rowid.rowid_relative_fno(rowid)fno,dbms_rowid.rowid_block_number(rowid)block_number,id,namefromt10;

altersystemdumpdatafile4block421;

altersystemdumpdatafile4block422;

8、提交方式

事务的提交:

如果一个事务修改了1000个块,现在这个事务要提交,那么需要修改1001个块中的“是否已提交信息”,1000个数据块+1个事务表。

这时,有可能这1000个块儿已经有800写进了磁盘下了,那么需不需要把这800个块儿重新写到磁盘,再提交,如果这样,会不会很慢?

答:

ORACLE针对这个问题,采了快速提交的办法,即当ORACLE发些这次事务修改的数据块过多,提交时,只会更新UNDO表空间里的事务表的“是否提交”

信息给更新了,而数据块事务槽的“是否已经提交”不作更新,或者更新少量。

所以数据块事务槽的“是否已经提交”信息,不一定准确,但是事务表里的“是否已提交”信息一定是准确的。

疑问解答:

为什么事务ID,即XID同时存在两个地方:

事务表和数据块里?

为什么需要数据块儿的SID还要指向事务表里的事务ID。

答:

如图所示,当另一个事务B需要对修改或查询同一个数据块的某一行时,而这一行已经被A事务修改,但是还没有提交。

些时ORACLE会走以下的程序流程:

从这里可以看出几个结论:

1)数据块的XID指向事务表是非常有用的。

2)ORACLE执行SELECT语句,也可能因为更改前面事务留在数据块事务槽里的“是否已提交”状态,而产了logbuffer,

进而生成redolog日志。

3)数据行上的ITL(事务槽的编号)指向事务槽,事务槽上有是琐已提交标识,这种机制实际上形成了ORACLE的行级锁。

4)对ORACLE最彻底的提交方式,是事务表里为“已提交”状态,数据块的事务槽为“已提交”状态,数据行的ITL被清除干净。

但实际上,数据行的ITL事务槽号没有清掉,留待下次查询时,再作清理,并且如果上一个事务较大时,数据块事务槽

里“是否已提交”标识不一定准确,但是事务表里的“是否已提交”信息一定是准确的。

ORACLE执行SELECT语句时,是很有可能产生REDOLOG日志的。

select读的过程分析如下:

ORACLE要读一个表,这个表有10000行,A事务8:

50开始读,8:

55时,另一个B事务删除了一行,并且提交了,9:

00时A事务读表有结果了,

请问ORACLE读到的是9999行,还是10000行?

答:

读到的是10000行,ORACLE是如何实现的呢?

ORACLE在时间8:

50时读这个表的时候,把时间点记下来,生成一个SCN(850),此时此刻,所有的

数据块的事务槽里的SCN都是<=850的。

1)在事务中,对四个地方的修改(数据行、事务槽、事务表、回滚块)全部产生的REDOLOG

2)对数据块的所有修改全部产生RODOLOG

一个数据块可以依据UNDO块数据一直往历史方向找出任意时间的数据块。

如图所示,

只要UNDO表空间足够大,那么可以利用回滚块和当前数据块,不断的构造出CR数据块,以些不断往历史方向构造。

ORACLE的ORA-01555错误

4、图解Oracleprivateredostrands机制

查看回滚段的使用情况,哪个用户正在使用回滚段的资源

select*fromv$transactiont,v$rollstatr,

v$rollnameu,v$sessions

wheres.taddr=t.addrandt.xidusn=r.usnandr.usn=u.usn

orderbys.username;

检查UNDOSegment状态

selectusn,xacts,rssize/1024/1024/1024,

hwmsize/1024/1024/1024,shrinks

fromv$rollstatorderbyrssize;

确定当前例程正在使用的UNDO表空间:

showparameterundo_tablespace;

select*fromv$parameterwherenamelike'%undo%';

显示数据库的所有UNDO表空间

select*fromdba_tablespaceswherecontents='UNDO';

显示UNDO表空间统计信息

selectto_char(begin_time,'HH24:

MI:

SS')BIGIN_TIME,

TO_CHAR(end_time,'HH24:

MI:

SS')END_TIME,undoblks

fromv$undostatA;

显示UNDO段统计信息

selecta.name,b.XACTS,b.WRITES,b.EXTENTSfromv$rollnamea,v$rollstatb

wherea.usn=b.usn;

显示活动事务信息

selecta.username,b.name,used_ublk

fromv$sessiona,v$rollnameb,v$transactionc

wherea.saddr=c.SES_ADDRandb.usn=c.XIDUSN

anda.username='HR';

UNDO表空间大小确定

selecttotalundo/((end-begin)*1440*60)undo_zize_per_secfrom

(selectmax(end_time)end,min(begin_time)begin,sum(undoblks)*8192totalundo

fromv$undostat

);

select140.741516648953*60/1024fromdual;

 

UNDO与REDO的关系:

他们没有什么关联

执行下面SQL语句,ORACLE的处理全过程:

updatet1setc1='A'WHEREC1='B'

1)找到包含C1='B'的数据据,假设是【4,120】

2)找到一个可用的UNDOBLOCK,假设是【2,300】

3)产生一个redo,去描述(保护)针对UNDOBLOCK的写入操作。

redo_addrSCNfile#block#operation

1009:

003400insert'B'

4)把'B'放入UNDOBLOCK.

5)产生一个REDO,去描述(保护)针对UNDOBLOCK的写入操作。

redo_addrSCNfile#block#operation

1009:

003400'B'-->'A’

6)把‘A’写入[4,120].

以后一担rollback,oracle可以直接把UNDO里的数据重新覆盖过来

ORACLE不提供脏读:

(我的修改,当我没有提交时,别人是读不到的)

比如:

A用户在9:

00执行一个查询SQL,这个表有10000条记录,这个SQL需要执行10分钟才能完成,

但是在9:

09时,B用户把这个表

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 生产经营管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1