oracle 11g undo 介绍: http://blog.csdn.net/dataminer_2007/article/details/41213945sql
undo 是 oracle 数据库中一个很是重要的机制, 在对数据库进行数据修改的时候, 可以为修改的数据构造一种前镜像数据(保存修改以前的旧值), 用来保证回滚对数据库的修改以及对多个用户同时访问的数据提供一致性读. 此外, undo 对于恢复数据库以及 flashback 查询以前时间的数据有着相当重要的做用,数据库
1.1 v$undostat: session
displays a histogram of statistical data to show how well the system is working. The available statistics include undo space consumption, transaction concurrency, and length of queries executed in the instance. You can use this view to estimate the amount of undo space required for the current workload. Oracle uses this view to tune undo usage in the system. The view returns NULL values if the system is in manual undo management mode.oracle
显示最近一段时间内关于 undo 表空间使用状况的统计信息, 能够用这个 view 来优化系统, 每隔 10 分钟自动增长一条数据, 总共只保存四天的数据, 若是要查询超过四天的数据就要使用 dba_hist_undostat, 这个 view 仅对于自动 undo 管理模式有效.优化
几个重要的字段说明:ui
UNDOTSN | NUMBER | 最近活动的 undo 表空间的 id |
UNDOBLKS | NUMBER | 当前时间段内消耗的 undo blocks 总数 |
TXNCOUNT | NUMBER | 当前时间段内执行的事务总数 |
MAXQUERYLEN | NUMBER | 当前时间段内执行单个查询花费的最长时间, 单位为秒 |
MAXQUERYID | NUMBER | 当前时间段内执行单个查询花费的最长时间的 sql id |
UNXPSTEALCNT | NUMBER | 其余事务尝试盗用未过时 undo 回滚段的次数 |
UNXPBLKRELCNT | NUMBER | 其余事务已经盗用未过时 undo 回滚段的数量 |
UNXPBLKREUCNT | NUMBER | 未过时的 undo 回滚段重用的数量 |
EXPSTEALCNT | NUMBER | 尝试盗用已通过期回滚段的次数 |
EXPBLKRELCNT | NUMBER | 已经盗用过时回滚段的数量 |
EXPBLKREUCNT | NUMBER | 已通过期回滚端重用的数量 |
SSOLDERRCNT | NUMBER | 返回 ora-01555 错误的次数, 若是 SSOLDERRCNT 大于 0, 说明 undo_retention 设置有问题, 须要增长 undo_retention 的大小 |
NOSPACEERRCNT | NUMBER | 空间不足申请新的 undo 表空间的次数 |
TUNED_UNDORETENTION | NUMBER | 已提交数据的undo 数据过时时间, 单位为秒 , 对于估计 flashback 可用的时间有用 |
SQL> select UNDOTSN, UNDOBLKS, TXNCOUNT, MAXQUERYLEN, MAXQUERYID, UNXPSTEALCNT, UNXPBLKRELCNT, UNXPBLKREUCNT, EXPSTEALCNT, EXPBLKRELCNT, EXPBLKREUCNT, SSOLDERRCNT, NOSPACEERRCNT, TUNED_UNDORETENTIONthis
from v$undostat;spa
1.2 dba_hist_undostat.net
显示全部的 v$undostat 的历史记录blog
1.3 dba_undo_extents:
显示数据库全部 undo 表空间的回滚段状况, 其中 status 的取值为 EXPIRED / UNEXPIRED / ACTIVE
Active: 活动状态, 说明当前这个回滚段被某个事务正在使用, 不会被其余事务使用
Expired: 已通过期, 随时能够被其余事务使用
Unexpired: 没有过时, 为了 undo_retention 的须要保留在 undo 表空间, 当空间不足时有可能被其余事务使用
1.4 v$rollname:
只有两个字段(usn, name), 就是一个回滚段 id 和 name, 一般和 v$rollstat 一块儿使用
1.5 v$rollstat:
统计回滚段表的使用状况
其中 xacts 表示当前回滚段上存在的活动事务的数量
status 的取值为 ONLINE / PENDING OFFLINE / OFFLINE / FULL
SQL> select a.usn, a.name, b.rssize, b.writes, b.xacts, b.waits, b.extends, b.status
from v$rollname a, v$rollstat b
where a.usn = b.usn;
1.6 dba_rollback_segs:
显示全部回滚段(包括 SYS 和 PUBLIC)的空间分配状况及当前状态
其中 status 的取值为 OFFLINE / ONLINE / NEEDS RECOVERY / PARTLY AVAILABLE / UNDEFINED
SQL> select owner, segment_name, tablespace_name, initial_extent, next_extents, status
from dba_rollback_segs;
2.1 undo 回滚段
在自动管理的 undo 表空间下, 数据库建立时会自动初始化 10 个回滚段, 从 v$rollname 中能够查询到这些自动建立的回滚段信息, 此外, oracle 会根据系统的负载状况自动建立以及释放回滚段.
众所周知, 回滚段保存的是修改的数据的前镜像数据, 对于 DML(insert, update, delete) 语句来讲, 回滚段保存的就是 DML 反向操做的数据, 若是是 insert 插入一行数据, 回滚段保存的就是删除该行的记录, 为了节约空间精简数据, 回滚段中只保存 insert 数据的 rowid, undo 只须要删除该 rowid 的记录便可;若是是 update 数据, 回滚段只保存修改字段的旧值, undo 只须要把旧值覆盖便可;若是是 delete 数据, 回滚段则须要保存整行的数据, undo 只须要把整行的数据插入便可.
由此可知, delete 操做产生的 undo(回滚段) 数据最多, 对于大批量的删除一定会对 undo 表空间产生比较大的冲击, 由此, 若是是删除整个表的数据能够用 truncate; 若是不是整个表的数据, 能够把分批删除数据.
回滚段的大小和数量对于系统相当重要, 全部 online 的回滚段(除了 system 的回滚段)都会被循环使用. 而每一个回滚段都包含有一些 extent(扩展), 当某个 extent 写满后会自动切换到另外一个 extent 继续使用.
2.2.2 undo 数据重用
对于自动扩展的 undo 表空间, oracle 会根据 undo_retention 的值做为保留 undo 数据的最少时间. 而对于固定大小又非 guarante 的 undo 表空间, oracle 会根据 undo 表空间大小及 v$undostat 的统计信息自动调整 以最大可能的保留 undo 数据, 这种状况下设置的 undo_retention 设置将被忽略. 此外, 若是 undo 表空间不足且没法自动扩展时, undo_retention 设置也将被忽略, 由于为了知足系统事务需求, 一些状态为 unexpired 的 undo 数据也有可能被置换重用.
当一个正在执行的事务须要更多 undo 空间,而 undo 表空间不足且没法扩展时, oracle 优先会重用当前回滚段下状态为 expired 的 undo extents, 若是没有就去其余回滚段下状态为 expired undo extents, 若是没有再回到当前回滚段中查找状态为 unexpired 的 undo extents, 若是尚未再去查找其余回滚段中状态为 unexpired 的 undo extents, 若是尚未就报空间不足的错误消息.
所以, 若是 undo_retention 为 900 秒(默认值), 并不必定意味着 undo 数据在 undo 表空间中保存 900 秒, 由于若是空间不足就会去覆盖不论是否已经 expired 的 已提交事务的undo 数据. 此外, undo_retention 时间到了以后, 并不必定意味这些 undo 数据在 undo 表空间中消失, 它只是并标示为 expired, 只要没有被其余事务的 undo 数据覆盖, 它会依然存在.
总之, 对于自动管理的 undo 表空间, 咱们依然天天要对它进行巡检, 保证 undo 表空间有足够的存储空间.
2.3 平常监控 undo 表空间
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
查看当前 undo 表空间大小
SQL> select sum(bytes)/1024/1024 "Current Undo Size(M)" from dba_data_files where tablespace_name='UNDOTBS1';
Current Undo Size(M)
------------------------------
10
查看当前 undo 表空间使用状况
SQL> select owner, segment_name, bytes/1024/1024 from dba_segments where tablesp
ace_name='UNDOTBS1';
OWNER SEGMENT_NAME BYTES/1024/1024
------------------------------ ------------------------------ --------------------------------------
SYS _SYSSMU20_781529403$ .3125
SYS _SYSSMU19_381980475$ .1875
SYS _SYSSMU18_53648357$ .1875
SYS _SYSSMU17_3412666006$ .3125
SYS _SYSSMU16_2828248073$ .3125
SYS _SYSSMU15_461690133$ .1875
SYS _SYSSMU14_3296674710$ .375
SYS _SYSSMU13_2498580566$ .25
SYS _SYSSMU12_2686240293$ .1875
SYS _SYSSMU11_103500371$ .125
10 rows selected.
SQL> select tablespace_name, status, sum(bytes)/1024/1024 from dba_undo_extents
group by tablespace_name, status;
TABLESPACE_NAME STATUS SUM(BYTES)/1024/1024
------------------------------ --------- ----------------------------------------------
UNDOTBS1 UNEXPIRED 1.5625
UNDOTBS1 EXPIRED .75
查看当前谁占用了 undo 表空间
SQL> select r.name "undo tablespace name",
rssize / 1024 / 1024 / 1024 "rssize(G)",
s.sid,
s.serial#,
s.username "username",
s.status,
s.sql_hash_value,
s.sql_address,
s.machine,
s.module,
substr(s.program, 1, 78) "program",
r.usn,
hwmsize / 1024 / 1024 / 1024,
shrinks,
xacts
from sys.v_$session s,
sys.v_$transaction t,
sys.v_$rollname r,
v$rollstat rs
where t.addr = s.taddr
and t.xidusn = r.usn
and r.usn = rs.usn
order by rssize desc;
2.3 切换 undo 表空间
SQL> create undo tablespace undo_david datafile 'g:\oracle\oradata\bakdb\undo_da
vid.dbf' size 10M;
Tablespace created.
SQL> alter system set undo_tablespace='undo_david' scope=both;
System altered.
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string undo_david
SQL> select segment_name, tablespace_name, status from dba_rollback_segs;
SEGMENT_NAME TABLESPACE_NAME STATUS
------------------------------ ------------------------------ ----------------
SYSTEM SYSTEM ONLINE
_SYSSMU1_719184344$ UNDOTBS1 OFFLINE
_SYSSMU2_2817567661$ UNDOTBS1 OFFLINE
_SYSSMU3_3680621135$ UNDOTBS1 OFFLINE
_SYSSMU4_237230745$ UNDOTBS1 OFFLINE
_SYSSMU5_2985270510$ UNDOTBS1 OFFLINE
_SYSSMU6_2775061352$ UNDOTBS1 OFFLINE
_SYSSMU7_3717448562$ UNDOTBS1 OFFLINE
_SYSSMU8_1685456424$ UNDOTBS1 OFFLINE
_SYSSMU9_2264502008$ UNDOTBS1 OFFLINE
_SYSSMU10_1467141425$ UNDOTBS1 OFFLINE
SEGMENT_NAME TABLESPACE_NAME STATUS
------------------------------ ------------------------------ ----------------
_SYSSMU11_103500371$ UNDO_DAVID ONLINE
_SYSSMU12_2686240293$ UNDO_DAVID ONLINE
_SYSSMU13_2498580566$ UNDO_DAVID ONLINE
_SYSSMU14_3296674710$ UNDO_DAVID ONLINE
_SYSSMU15_461690133$ UNDO_DAVID ONLINE
_SYSSMU16_2828248073$ UNDO_DAVID ONLINE
_SYSSMU17_3412666006$ UNDO_DAVID ONLINE
_SYSSMU18_53648357$ UNDO_DAVID ONLINE
_SYSSMU19_381980475$ UNDO_DAVID ONLINE
_SYSSMU20_781529403$ UNDO_DAVID ONLINE
21 rows selected.
SQL> select usn,xacts,status from v$rollstat;
USN XACTS STATUS
---------- ---------- ---------------
0 0 ONLINE
11 0 ONLINE
12 0 ONLINE
13 0 ONLINE
14 0 ONLINE
15 0 ONLINE
16 0 ONLINE
17 0 ONLINE
18 0 ONLINE
19 0 ONLINE
20 0 ONLINE
11 rows selected.
要等到旧的 undo 表空间 undotbs1 上的回滚段都 offline 后才能 drop
SQL> drop tablespace undotbs1;
Tablespace dropped.
SQL> select tablespace_name, file_name, status from dba_data_files where tablesp
ace_name like 'UNDO%';
TABLESPACE_NAME FILE_NAME STATUS
------------------------------ ------------------------------ --------- ----------------------------------------------------------
UNDO_DAVID G:\ORACLE\ORADATA\BAKDB\UNDO_DAVID.DBF AVAILABLE
虽然 drop 成功, 可是若是有其余查询须要用到旧的 undo 表空间 undotbs1 上的数据时就会提示 ora-01555 的错误
SQL> select * from dba_undo_extents where tablespace_name='UNDOTBS1';
总之, 切换系统当前 undo 表空间到新建的 undo 表空间几乎能够随时执行成功, 可是若是要删除旧的 undo 表空间必定要等到该 undo 空间里全部的回滚段所有 offline. 千万别在尚有回滚段处于 online 状态强制删除数据文件.