UNDO是Oracle中的一个很重要的机制,在对数据库进行修改的时候,Oracle会将数据块上修改之前的数据(称为前映像,before image)保存在回滚段中,这样当我们需要进行回滚(rollback)的时候就很容易能从回滚段中将之前的数据取出来将数据块上面的数据还原回来。
当然上面所说的只是UNDO的最基本的一个用途,实际上UNDO的应用远不止于此,下面就列举一下UNDO的各种作用(对于11gR2版本,不同版本会有些功能差异):
(miki西游 @mikixiyou 原文链接: http://mikixiyou.iteye.com/blog/1769403)
1,回退事务
当执行DML操作修改数据时,UNDO数据被存放到UNDO段,而新数据则被存放到数据段中,如果事务操作存在问题,旧需要回退事务,以取消事务变 化.假定用户A执行了语句UPDATE emp SET sal=1000 WHERE empno=7788后发现,应该修改雇员7963的工资,而不是雇员7788的工资,那么通过执行ROLLBACK语句可以取消事务变化.当执行 ROLLBACK命令时,oracle会将UNDO段的UNDO数据800写回的数据段中.
2,读一致性
用户检索数据库数据时,oracle总是使用用户只能看到被提交过的数据(读取提交)或特定时间点的数据(SELECT语句时间点).这样可以确保 数据的一致性.例如,当用户A执行语句UPDATE emp SET sal=1000 WHERE empno=7788时,UNDO记录会被存放到回滚段中,而新数据则会存放到EMP段中;假定此时该数据尚未提交,并且用户B执行SELECT sal FROM emp WHERE empno=7788,此时用户B将取得UNDO数据800,而该数据正是在UNDO记录中取得的.
3,事务恢复
事务恢复是例程恢复的一部分,它是由oracle server自动完成的.如果在数据库运行过程中出现例程失败(如断电,内存故障,后台进程故障等),那么当重启oracle server时,后台进程SMON会自动执行例程恢复,执行例程恢复时,oracl会重新做所有未应用的记录.回退未提交事务.
4,倒叙查询(FlashBack Query)
倒叙查询用于取得特定时间点的数据库数据,它是9i新增加的特性,假定当前时间为上午11:00,某用户在上午10:00执行UPDATE emp SET sal=3500 WHERE empno=7788语句,修改并提交了事务(雇员原工资为3000),为了取得10:00之前的雇员工资,用户可以使用倒叙查询特征.
UNDO管理使用的数据字典
1、直接相关的数据字典
9i之前手工管理时就存在的数据字典
V$ROLLNAME:回滚段名称和回滚段ID对应表。
V$ROLLSTAT:在使用AUM时,该视图保存着所有UNDO表空间中每一个已分配的回滚段当前状态以及相关的统计信息,不显示状态在OFFLINE的回滚段。
DBA_ROLLBACK_SEGS:此字典显示所有回滚段的当前状态以及与存储空间分配相关的信息。
9i之后新增的数据字典
V$UNDOSTAT:保存了某一时间段的整个UNDO表空间使用的统计信息以及UNDO自动优化的结果,默认情况下每10分钟增加一条记录,并只保留最近的576条(4天。在10g及之前版本中此记录为1008,或7天)的信息,超过期限的数据只能在DBA_HIST_UNDOSTAT中找到。此字典仅对自动UNDO管理模式有效。
DBA_UNDO_EXTENTS:保存了UNDO表空间中所有已分配的数据区的存储空间分配情况与使用情况,是得到UNDO数据当前存在状态的一个重要的视图。
DBA_HIST_UNDOSTAT:保存了所有V$UNDOSTAT所存在的数据的一个历史记录,10g开始新增字典。
2、间接相关的数据字典
事务相关
V$TRANSACTION:当前正在进行事务的信息,与UNDO管理相关的是当前事务所涉及的UNDO段,UNDO空间占用等等信息。具体的前面已经有介绍。
UNDO表空间相关
DBA_EXTENTS:与DBA_UNDO_EXTENTS类似。
DBA_SEGMENTS:与DBA_ROLLBACK_SEGS类似。
DBA_DATA_FILES:关联计算UNDO表空间大小而用。
UNDO管理的SQL语句
我收录了一些有关Undo表空间与回滚段的SQL查询语句
V$ROLLSTAT记录的是整个UNDO表空间各个回滚段使用情况的统计,属于横向的;而V$UNDOSTAT记录的则是各个时间段上面整个UNDO使用情况的统计,属于纵向的。
--与回滚段相关的几个系统参数
transactions_per_rollback_segment
transactions
max_rollback_segments
rollback_segments 回滚段类型为public则与该参数无关
--相关的几个视图:
DBA_UNDO_EXTENTS
GV$UNDOSTAT
V$UNDOSTAT
DBA_ROLLBACK_SEGS
GV$ROLLSTAT
V$ROLLNAME
V$ROLLSTAT
---分析UNDO表空间使用情况
SELECT seg.tablespace_name "Tablespace Name", ts.bytes/1024/1024 "TS Size(MB)",
ue.status "UNDO Status", count(*) "Used Extents",
round(sum(ue.bytes)/1024/1024, 2) "Used Size(MB)",
round(sum(ue.bytes)/ts.bytes*100, 2) "Used Rate(%)"
FROM dba_segments seg, DBA_UNDO_EXTENTS ue,
(SELECT tablespace_name, sum(bytes) bytes
FROM dba_data_files GROUP BY tablespace_name) ts
WHERE ue.segment_NAME=seg.segment_NAME and seg.tablespace_name=ts.tablespace_name
GROUP BY seg.tablespace_name, ts.bytes, ue.status
ORDER BY seg.tablespace_name;
---分析 UNDO 扩展的使用情况
SELECT TABLESPACE_NAME,STATUS,TRUNC(SUM(BLOCKS) * 8 / 1024) AS "Size M",
COUNT(*) Undo_Extent_Num
FROM DBA_UNDO_EXTENTS
GROUP BY TABLESPACE_NAME, STATUS
---监控undo表空间
SELECT BEGIN_TIME, END_TIME, UNDOTSN, UNDOBLKS, TXNCOUNT,
MAXCONCURRENCY AS "MAXCON"
FROM V$UNDOSTAT;
--查询是否有回滚段的争用
select * from v$waitstat;
SELECT name, waits, gets, waits/gets "Ratio"
FROM v$rollstat a, v$rollname b
WHERE a.usn = b.usn;
---查看回滚段的统计信息:
SELECT n.name, s.extents, s.rssize, s.optsize, s.hwmsize, s.xacts, s.status
FROM v$rollname n, v$rollstat s
WHERE n.usn = s.usn;
--查看回滚段的使用情况,哪个用户正在使用回滚段的资源:
SELECT s.sid,s.username,s.PROGRAM,s.MACHINE,u.name,t.used_ublk
FROM v$transaction t, v$rollstat r, v$rollname u, v$session s
WHERE s.taddr = t.addr
AND t.xidusn = r.usn
AND r.usn = u.usn
ORDER BY s.username;
--查询回滚段的事务回退率
transaction rollbacks/(transaction rollbacks+user commits)
select name,value from v$syssstat where name in('user commits','transaction rollbacks');
--查询获取回滚段数据的时候数据缓冲区中copy的数据块的数量
select count(*) from x$bh where state=3;
--查询在SGA中回滚段的块的数量USN=n,则回滚段头class为11+2n,回滚段块为12+2n
select usn from v$rollstat;
select class,count(*) from x$bh where class>10 group by class;
--查询数据库的的回滚段情况
select segment_id,segment_name from dba_rollback_segs;
--指定使用某个回滚段
set transaction use rollback segment _SYSSMU4$
--查询回滚段在使用,扩展,回缩的时候extent在循环的次数
select usn,wraps from v$rollstat;
--查询回滚段收缩的情况
select usn,optsize,shrinks from v$rollstat;
--切换undo表空间到新的表空间(注意修改pfile或者spfile参数)
alter system set undo_tablespace=UNDOTBS1 scope=both;
---创建undo表空间
CREATE UNDO TABLESPACE UNDOTBS2 DATAFILE 'E:\ORACLE\ORA92\ORCL9\UNDOTBS02.DBF' size 11M reuse AUTOEXTEND ON;
---改变(Altering) an Undo Tablespace
Adding a datafile
Renaming a datafile
Bringing a datafile online or taking it offline
Beginning or ending an open backup on a datafile
---增加数据文件
ALTER TABLESPACE UNDOTBS2
ADD DATAFILE 'E:\ORACLE\ORA92\ORCL9\UNDOTBS03.DBF' size 2M AUTOEXTEND ON NEXT 1M
MAXSIZE UNLIMITED;
--drop undo表空间
DROP TABLESPACE UNDOTBS2; ---INCLUDING CONTENTS.
--不指定undo表空间
ALTER SYSTEM SET UNDO_TABLESPACE = '';
--设置retention值:
ALTER SYSTEM SET UNDO_RETENTION = 5;
UNDO管理的RETENTION
数据库初始化参数UNDO_RETENTION是回滚段保留的时间值的最小阀值。
生效条件是:
如果,Oracle数据库使用的UNDO表空间是自动扩展,则会依据初始化参数undo_retention指定的值来决定undo段的保留时间。
如果,Oracle数据库使用的UNDO表空间是固定大小的,则初始化参数undo_retention将被忽略,undo段空闲如果不足,会自动覆盖非活动的undo段。
但在10g以后,这个功能有了调整。UNDO表空间有一个新的属性retention,它的值如果是GUARANTEE,在固定大小的UNDO表空间中初始化参数undo_retention会生效,继续将undo段保留时间强制为该参数指定的值。
UNDO表空间属性retention的默认值是NOGUARANTEE,可以通过dba_tablespaces去查询。
但是,我遇到的案例是这样的情况。UNDO表空间是固定大小,设置了undo_retention值,所有的非过期的回滚段在undo空闲空间不足时也没有自动释放,出现ORA-30036错误导致事务中止。咨询ORACLE官方,说这可能是bug。
因此,只要设置了undo_retention,UNDO表空间使用率就可能不足。故该参数值需要调整合适到合适大小。
http://www.dbabeta.com/上有几篇文章对此整理的比较好,可以参考。
http://www.dbabeta.com/2010/undo-management_auto-undo-management.html
http://www.dbabeta.com/2010/undo-management_data-dictionary.html