--==================================
--Oracle
回滚(ROLLBACK)和撤销(UNDO)
--==================================
一、回滚(ROLLBACK)和撤销(UNDO)
回滚和前滚是保证Oracle数据库中的数据处于一致性状态的重要手段。
在9i版本以前
Oracle使用数据库中的回滚段来实现未提交数据或因系统故障导致实例崩溃时进行回滚操作
每一个表空间需要创建回滚段,各个表空间对回滚段实现各自的管理
在9i及后续版本
提供了一种新的回滚数据的管理方式,即使用Oracle自动管理的撤销(Undo)表空间
自动撤销管理表空间统一管理所有DML的回滚操作,简化了对于回滚工作的管理
在9i,10g中的回滚段仅仅用作保留向后兼容
撤销段代替了原有版本中的回滚段,因此本文所有描述均使用撤销
撤销的实质意味着将所作的修改退回到修改前的状态,即倒退所有DML语句
二、撤销段中的内容及相关特性
对于任何DML操作而言,必须同时处理数据块和撤销块,并且还会生成重做信息
在ACID中,A、C、I要求生成撤销,D则要求生成重做
INSERT:
撤销段记录插入记录的rowid,如果需要撤销,则根据rowid将该记录删除即可
UPDATE:
撤销段记录被更新字段的原始值,撤销时将原始值覆盖新值即可
DELETE:
撤销段记录整行的数据,撤销时执行反向操作将该记录插入原表
由上可知,UNDO段中的内容总结如下:
数据为修改之前的副本
从每个改变数据的事务中获得
在事务结束前一直被保留
UNDO段中数据的作用:
用于回滚操作
读一致性和闪回查询
用于事务失败时的恢复
UNDO段与事务:
一个事物的启动,Oracle将为其分配仅仅一个UNDO段,若该段用完,则Oracle会自动为该UNDO段添加另一个区间(extent)
一个UNDO段能够同时为多个事务服务
UNDO段与UNDO表空间:
UNDO段中的内容存储在UNDO表空间
任意给定时刻只能使用一个UDNO表空间
UNDO表空间必须被创建为持久的、本地管理、可自动扩展的表空间
正在使用的UNDO表空间不能撤销或删除
UNDO表空间使用循环写的方式,与联机日志文件写相似,不同的是UNDO中可以设置了undo_retention 保留时间
UNDO段的两种管理方式:
AUTO
自动管理(推荐)
MANUAL
手动管理(仅保留)
三、与撤销相关的几个参数
--查看本机中Oracle的版本
SQL> SELECT *
FROM v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise
Edition Release 10.2.0.1.0 -
Prod
PL/SQL Release 10.2.0.1.0
- Production
CORE
10.2.0.1.0
Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 -
Production
--查看和UNDO相关的参数
SQL> SHOW PARAMETER
undo;
NAME
TYPE
VALUE
------------------------------------
----------- ------------------------------
undo_management
string
MANUAL
undo_retention
integer
900
undo_tablespace
string
UNDOTBS1
undo_management:
设置数据库的撤销段是否使用自动管理模式,值可以为auto或manual,当为manual时将不使用撤销段,即不使用自动管理模式
该参数为静态参数,修改后需重启实例才能生效
undo_retention:
指定撤销段数据在undo段中为非活动状态后被覆盖前保留的时间,单位为秒。在undo_management位auto时生效,为动态参数
undo_tablespace:
指定使用哪个表空间来实现数据的撤销,在undo_management位auto时生效,为动态参数
retention guarantee子句:
保证撤销保留,使用下面的操作来实现
ALTER TABLESPACE
undo_tablespace_name RETENTION GUARANTEE;
--下面的查询中是当undo_management为manual时的结果集,可以看出撤销表空间的撤销段都处于offline状态
SQL> SELECT segment_name,tablespace_name,status FROM
dba_rollback_segs;
SEGMENT_NAME
TABLESPACE_NAME
STATUS
------------------------------
------------------------------ ----------------
SYSTEM
SYSTEM
ONLINE
_SYSSMU1$
UNDOTBS1
OFFLINE
_SYSSMU2$
UNDOTBS1
OFFLINE
_SYSSMU3$
UNDOTBS1
OFFLINE
_SYSSMU4$
UNDOTBS1
OFFLINE
_SYSSMU5$
UNDOTBS1
OFFLINE
_SYSSMU6$
UNDOTBS1
OFFLINE
_SYSSMU7$
UNDOTBS1
OFFLINE
_SYSSMU8$
UNDOTBS1
OFFLINE
_SYSSMU9$
UNDOTBS1
OFFLINE
_SYSSMU10$
UNDOTBS1
OFFLINE
--在undo_management 参数为manual时,对scott.emp插入一条新记录,收到了错误提示
--非系统表空间不能够使用回滚段
SQL> INSERT INTO
scott.emp(empno,ename,salary)
2
VALUES(6666,'Jenney',3000);
INSERT INTO scott.emp(empno,ename,salary)
*
ERROR at line 1:
ORA-01552: cannot use
system rollback segment
for non-system tablespace 'USERS'
--查看段的类型,发现仅仅system表空间存在ROLLBACK 段,所以前一条插入语句收到错误提示
SQL> SELECT DISTINCT segment_type,tablespace_name FROM dba_segments
2
ORDER BY tablespace_name;
SEGMENT_TYPE
TABLESPACE_NAME
------------------
------------------------------
INDEX
EXAMPLE
INDEX PARTITION
EXAMPLE
LOBINDEX
EXAMPLE
LOBSEGMENT
EXAMPLE
NESTED TABLE
EXAMPLE
TABLE
EXAMPLE
TABLE PARTITION
EXAMPLE
INDEX
SYSAUX
INDEX PARTITION
SYSAUX
LOB PARTITION
SYSAUX
LOBINDEX
SYSAUX
SEGMENT_TYPE
TABLESPACE_NAME
------------------
------------------------------
LOBSEGMENT
SYSAUX
NESTED TABLE
SYSAUX
TABLE
SYSAUX
TABLE PARTITION
SYSAUX
CLUSTER
SYSTEM
INDEX
SYSTEM
LOBINDEX
SYSTEM
LOBSEGMENT
SYSTEM
NESTED TABLE
SYSTEM
ROLLBACK
SYSTEM
--与之前的版本兼容的回滚段
TABLE
SYSTEM
SEGMENT_TYPE
TABLESPACE_NAME
------------------
------------------------------
TABLE
TBS1
TYPE2 UNDO
UNDOTBS1
--9i之后使用的撤销段
INDEX
USERS
LOBINDEX
USERS
LOBSEGMENT
USERS
NESTED TABLE
USERS
TABLE
USERS
--下面将undo_management改为支持自动管理,需要重启实例
SQL> ALTER SYSTEM SET undo_management = 'auto' SCOPE
= SPFILE;
System altered.
SQL> SHUTDOWN IMMEDIATE;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> STARTUP;
ORACLE instance started.
Total System Global Area 251658240
bytes
Fixed Size
1218796 bytes
Variable Size
67110676 bytes
Database Buffers
180355072 bytes
Redo Buffers
2973696 bytes
Database mounted.
Database opened.
--再次查看dba_rollback_segs视图所有的撤销段全部处于online状态
--注意第一行为system表空间的撤销段,用于系统表空间的撤销
SQL> SELECT segment_name,tablespace_name,status FROM
dba_rollback_segs;
SEGMENT_NAME
TABLESPACE_NAME
STATUS
------------------------------
------------------------------ ----------------
SYSTEM
SYSTEM
ONLINE
_SYSSMU1$
UNDOTBS1
ONLINE
_SYSSMU2$
UNDOTBS1
ONLINE
_SYSSMU3$
UNDOTBS1
ONLINE
_SYSSMU4$
UNDOTBS1
ONLINE
_SYSSMU5$
UNDOTBS1
ONLINE
_SYSSMU6$
UNDOTBS1
ONLINE
_SYSSMU7$
UNDOTBS1
ONLINE
_SYSSMU8$
UNDOTBS1
ONLINE
_SYSSMU9$
UNDOTBS1
ONLINE
_SYSSMU10$
UNDOTBS1
ONLINE
由上面的示例可知:
ROLLBACK
段:
--与之前的版本兼容的回滚段
TYPE2 UNDO
段: --9i之后使用的撤销段
关于回滚,一个时刻仅能使用一种类段类型,即要么使用与以前版本兼容的回滚段,要么使用撤销段
事实上,在9i之后仅仅支持撤销段,从上面错误的提示即可证实
--查看DML语句产生的事务
SQL> SHOW USER;
USER is "SYS"
SQL> SELECT *
FROM scott.emp WHERE
ename = 'SCOTT';
EMPNO
ENAME
JOB
MGR HIREDATE
SALARY
DEPTNO
---------- --------------- ---------
---------- --------- ---------- ----------
7788
SCOTT
ANALYST
7566 19-APR-87
3500
20
SQL> UPDATE scott.emp SET sal
= sal * 2 WHERE ename = 'SCOTT';
1 row updated.
SQL> SELECT addr,xidusn,status,start_time,used_ublk
2
FROM v$transaction;
ADDR
XIDUSN STATUS
START_TIME
USED_UBLK
-------- ---------- ----------------
-------------------- ----------
2DA2B17C
9 ACTIVE
07/10/10 20:29:08
1
--查看当前哪些用户使用撤销段以及段的大小,启动时间,活动状态等
SQL> SELECT t.xidusn,t.start_time,t.used_ublk,t.status,
s.username,r.segment_name
FROM v$transaction t
JOIN v$session s
ON t.ses_addr =
s.saddr
JOIN dba_rollback_segs
r
ON r.segment_id =
t.xidusn ;
XIDUSN START_TIME
USED_UBLK STATUS
USERNAME
SEGMENT_NAME
---------- --------------------
---------- ---------------- ------------------------------
-------------
9
07/10/10 20:29:08
1 ACTIVE
SYS
_SYSSMU9$