一、基础
UNDO是源数据的一个副本,为每个修改数据的事务保留快照,
其保存时间至少要在事务结束之后。
用途包括:
回滚操作
一致性读
闪回查询、闪回事务、闪回表
恢复失败的事务
UNDO信息可以被所有事务使用,直到以下情况:
用户回滚事务
用户终止事务(提交)
执行了DDL操作
用户会话非正常结束
用户会话正常结束并退出
每个事务只能申请一个UNDO段,而一个UNDO段可以为多个事务所使用。
并行DML和DDL操作可以使用多个UNDO段。
UNDO段是存在UNDO表空间中的。在繁忙的OLTP系统中有大量短事务,可能会发生文件头的争用。将UNDO表空间存到多个数据文件,可以解决此问题。
某一时刻,只能有一个UNDO表空间时可用的。UNDO段是循环使用的,因此每个段至少有两个区。默认的最大的区(extents)数量取决于数据库块大小,但已经非常大了。
UNDO表空间时本地管理的固定表空间。
由于失败事务恢复时需要撤销数据(UNDO数据),因此UNDO表空间只能在mount状态下恢复。
二 、UNDO的自动管理:
UNDO数据及为UNDO表空间分配的空间完全自动管理;
服务于所有会话;
在自动扩展的表空间自己挑有来满足长时间的运行;
在大小可变的表空间为支持闪回操作的最大保留时间,使用自动调优(self-tuning)
配置UNDO保留策略
修改UNDO表空间为可变大小
避免空间和快照太旧的错误
oracle提供了undo段,一种完全自动管理所有会话独占的表空间中undo信息和空间的机制。
系统通过自动调整,提供最大可能的UNDO信息保留策略。更准确地讲,自动扩展的表空间UNDO保留周期比运行时间最长的活动查询的时间还要长。
对于有空间限制的undo表空间,数据库动态调整到可能的最大保留周期。
11g中默认是UNDO自动管理的。手工UNDO管理是为了对oracle 8i及其之前版本提供向下兼容,要求DBA有更多的交互。
在手工UNDO管理模式下,UNDO空间是通过撤销段(rollback segments),而非UNDO表空间来实现管理的。
oracle推荐使用自动管理UNDO表空间。尽管默认设置是自动管理,但在使用闪回操作时还是需要手工的某些操作。UNDO空间管理应该确保不发生空间错误(占用空间太大或“snapshot too old”错误等)
三、UNDO保留策略的配置:
UNDO_RETENTION指定已经提交的事务,其UNDO信息被保留至少多少秒。
以下情况下需要设置该参数:
1)UNDO表空间开启了自动扩展;
2)你想要为LOBS设置恢复保留策略;
3)想要验证保留策略
其他情况下,undo_retention设置被忽略。
UNDO数据分为三类:
未提交的
已提交的
过期的
默认的UNDO行为会重写已提交但未过期的事务,而不会在缺少undo空间时使活动的会话失败。
该行为可以通过修改为确认的保留策略(guaranteed retention)来改变。
通过guaranteed retention,强制保证undo的恢复保留时间,即使事务失败也会保证。
guaranteed retention是表空间的参数,而不是初始化参数。该属性只能有sql命令修改。
修改语句为:
alter tablespace undotbs1 retention guarantee|NOGUARANTEE;
只能对UNDO表空间使用给参数。
四、修改undo表空间为可变大小
原因:
支持闪回操作
限制表空间的增长
基本步骤:
常规运行一段时间,自动调优机制创建需要的最小空间大小;
使用undo advisor计算将来增长所需要的空间大小;
将undo表空间变为可变大小
指定可变的UNDO表空间大小时,需要选择一个足够大的大小来避免以下错误:
DML操作由于没有足够的UNDO空间容纳新事务;
快照太旧错误,由于没有足够的UNDO空间保证读一致性。
oracle建议运行一个规律的、完整的负载,是undo表空间增长到其需要的最小大小。
自动增长数据包括运行时间很长的查询的周期、UNDO生成率。对于没有闪回操作、不希望运行长查询(longer-running queries)的系统,可以给予这些数据来计算undo表空间的最小大小。
还可以使用undo advisor,输入期望的长查询和闪回的undo周期。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
实验:
Connected to Oracle Database 10g Release 10.2.0.1.0
Connected as SYS
SQL> select tablespace_name from dba_tablespaces;
TABLESPACE_NAME
---------------
SYSTEM
UNDOTBS1
SYSAUX
TEMP
USERS
NBSTBL
TSPITR1
TSPITR2
8 rows selected
SQL> select * from dba_data_files;
FILE_NAME FILE_ID TABLESPACE_NAME BYTES BLOCKS STATUS RELATIVE_FNO AUTOEXTENSIBLE MAXBYTES MAXBLOCKS INCREMENT_BY USER_BYTES USER_BLOCKS ONLINE_STATUS
-------------------------------- ---------- ------------------ ---------- ---------- --------- ------------ -------------- ---------- ---------- ------------ ---------- ----------- -------------
D:\ORADATA\TEST\USERS01.DBF 4 USERS 218890240 26720 AVAILABLE 4 YES 3435972198 4194302 160 218824704 26712 ONLINE
D:\ORADATA\TEST\SYSAUX01.DBF 3 SYSAUX 346030080 42240 AVAILABLE 3 YES 3435972198 4194302 1280 345964544 42232 ONLINE
D:\ORADATA\TEST\UNDOTBS01.DBF 2 UNDOTBS1 629145600 76800 AVAILABLE 2 YES 3435972198 4194302 640 629080064 76792 ONLINE
D:\ORADATA\TEST\SYSTEM01.DBF 1 SYSTEM 513802240 62720 AVAILABLE 1 YES 3435972198 4194302 1280 513736704 62712 SYSTEM
D:\ORADATA\TEST\NBSTBL.DBF 5 NBSTBL 83886080 10240 AVAILABLE 5 YES 3435972198 4194302 1280 83820544 10232 ONLINE
D:\ORADATA\TEST\TSPITR1.DBF 6 TSPITR1 5242880 640 AVAILABLE 6 NO 0 0 0 5177344 632 ONLINE
D:\ORADATA\TEST\TSPITR2.DBF 7 TSPITR2 5242880 640 AVAILABLE 7 NO 0 0 0 5177344 632 ONLINE
7 rows selected
SQL> create undo tablespace undotbs02 datafile 'd:\ORADATA\TEST\UNDOTBS02.DBF' size 5M ;
Tablespace created
SQL> select tablespace_name,bytes/1024/1024 "SIZE MB" from dba_data_files where tablespace_name='UNDOTBS1';
TABLESPACE_NAME SIZE MB
------------------------------ ----------
UNDOTBS1 600
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
SQL> alter system set undo_tablespace='UNDOTBS02';
System altered
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS02
SQL> select count(1) from dba_tables;
COUNT(1)
----------
1572
(一)某个事务耗尽UNDO表空间
SQL> create table t as select * from dba_tables;
Table created
SQL> insert into t select * from dba_tables;
1572 rows inserted
SQL>
SQL> begin
2 insert into t select * from t;
3 insert into t select * from t;
4 insert into t select * from t;
5 insert into t select * from t;
6 insert into t select * from t;
7 delete from t where rownum<1000;
8 insert into t select * from t where rownum<2000;
9 delete from t where rownum<2000;
10 insert into t select * from t;
11 insert into t select * from t;
12 insert into t select * from t;
13 insert into t select * from t;
14 insert into t select * from t;
15 insert into t select * from t where rownum<3000;
16 delete from t where rownum<5000;
17 end;
18 /
begin
insert into t select * from t;
insert into t select * from t;
insert into t select * from t;
insert into t select * from t;
insert into t select * from t;
delete from t where rownum<1000;
insert into t select * from t where rownum<2000;
delete from t where rownum<2000;
insert into t select * from t;
insert into t select * from t;
insert into t select * from t;
insert into t select * from t;
insert into t select * from t;
insert into t select * from t where rownum<3000;
delete from t where rownum<5000;
end;
ORA-30036: 无法按 8 扩展段 (在还原表空间 'UNDOTBS02' 中)
ORA-06512: 在 line 13
报此错误时,整个事务回滚。
oracle需要保证事务的UNDO信息完整地记录到UNDO表空间中。
(二)闪回失败
SQL> set time on
13:52:44 SQL> select count(1) from t as of timestamp sysdate-10/1440;
select count(1) from t as of timestamp sysdate-10/1440
ORA-01555: 快照过旧: 回退段号 15 (名称为 "_SYSSMU15$") 过小
前面看到设置的参数undo_retention=900,即undo数据的保留时间是900秒,
但由于在这期间做了大量的DML操作,为了保证事务的正常运行,10分钟之前的数据已经被移出UNDO表空间了。
(三)设置guarantee retention
13:55:40 SQL> select tablespace_name,RETENTION from dba_tablespaces;
TABLESPACE_NAME RETENTION
------------------------------ -----------
SYSTEM NOT APPLY
UNDOTBS1 NOGUARANTEE
SYSAUX NOT APPLY
TEMP NOT APPLY
USERS NOT APPLY
NBSTBL NOT APPLY
TSPITR1 NOT APPLY
TSPITR2 NOT APPLY
UNDOTBS02 NOGUARANTEE
13:56:37 SQL> alter tablespace undotbs02 retention guarantee;
Tablespace altered
14:01:00 SQL> delete from t2 where rownum<1000;
delete from t2 where rownum<1000
ORA-30036: 无法按 8 扩展段 (在还原表空间 'UNDOTBS02' 中)
14:01:10 SQL> drop table t2;
drop table t2
ORA-00604: 递归 SQL 级别 1 出现错误
ORA-30036: 无法按 8 扩展段 (在还原表空间 'UNDOTBS02' 中)
14:02:23 SQL> select tablespace_name,RETENTION from dba_tablespaces;
TABLESPACE_NAME RETENTION
------------------------------ -----------
SYSTEM NOT APPLY
UNDOTBS1 NOGUARANTEE
SYSAUX NOT APPLY
TEMP NOT APPLY
USERS NOT APPLY
NBSTBL NOT APPLY
TSPITR1 NOT APPLY
TSPITR2 NOT APPLY
UNDOTBS02 GUARANTEE
修改UNDO表空间的retention属性后,可以在dba_tablespaces的retention中看到变化。
这时oracle被强制要求满足undo_retention。也就是说总是可以通过闪回看到undo_retention值所指定时间点(我的数据库是900s之前)的数据。
如果频繁的事务提交使oracle可能无法满足该约束,则事务被回滚。报错undo表空间太小。
(四)环境恢复
若希望继续使用undotbs02表空间,但不需要guarantee retention,执行:
14:03:04 SQL> alter tablespace undotbs02 retention NOGUARANTEE;
Tablespace altered
但通常来说我创建的5M的undo表空间太小了,还是需要恢复原来的undotbs1:
14:09:35 SQL> alter system set undo_tablespace='UNDOTBS1';
System altered
14:10:46 SQL> show parameter undo_
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
UNDO表空间还可以设置为autoextended,即自动增长。这时undo_retention的设置就影响到UNDO表空间的大小。
没有了空间限制,oracle就通过必要的UNDO表空间增长来保证undo_retention参数到当前时间的所有undo数据没有被移出UNDO表空间。
从管理的角度讲,不应该让UNDO表空间没有限制地增长下去。
而短时间内频繁的UNDO数据生成应该得到控制,而不是让UNDO空间无限制地增长。
设置一个合理的UNDO表空间大小,需要根据一个有代表性的周期中事务运行情况以及undo_retention大小来估算。
我们一个用于数据迁移的测试环境设置的UNDO表空间大小为20G。
OLTP和OLAP系统,由于不同的用途,undo表空间设置应该是不一样的。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26451536/viewspace-766133/
,如需转载,请注明出处,否则将追究法律责任。