zt http://www.blogjava.net/wxqxs/archive/2008/08/31/226737.html
回滚段用于存放数据修改之前的值(也包括数据修改前的位置)。回滚段的头部包含正在使用的该回滚段事务的信息。一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚段可以存放多个事务的回滚信息。
事务级的读一致性:
SET TRANSACTION READ ONLY;
SET TANNSACTION SERIALIZABLE;
create rollback segment rb01
tablespace rbs1
storage (
initial 100 K
next 100 K
minextents 20
maxextents 100
optimal 2000 K );
注意:
(2) 更改ONLINE/OFFLINE状态
alter rollback segment rb01 online ;
alter rollback segment rb01 offline ;
当回滚段创建后,回滚段是离线的,不能被数据库使用,为了使回滚段被事务利用,必须将回滚段在线。
(3) 更改OPTIMAL参数
alter rollback segment rb01
storage ( maxextents 200
optimal 2048 K );
(4) 缩小回滚段
alter rollback segment rb01 shrink to 2048 K;
-- 有 OPTIMAL 参数时 , 缩小到 OPTIMAL 值
alter rollback segment rb01 shrink ;
-- 没有 OPTIMAL 参数时 , 缩小到 MINEXTENTS 所对应的值
(5) 修改INITIAL/NEXT参数
-- 修改 NEXT 时 , 总应该同时修改 INITIAL.
--INITIAL 参数无法直接修改 , 只能先 DROP, 然后再 CREATE.
drop rollback segment rb01;
create rollback segment rb01
tablespace rbs1
storage ( initial 100 K
next 100 K
minextents 20
maxextents 121
optimal 2000 K );
(6) 在事务中使用特定的回滚段
set transaction use rollback segment rb01;
(7) 常用的有关回滚段的系统数据字典
DBA_ROLLBACK_SEGS --DBA_SEGMENTS 中的 ROLLBACK 类型
V$ROLLNAME
V$ROLLSTAT
V$TRANSACTION --V$SESSION
回滚段的基本信息, 例:
SQL>SELECT segment_name,tablespace_name,owner,status FROM dba_rollback_segs;
SQL>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;
FROM v$session s,v$transaction t
WHERE s.saddr=t.ses_addr;
USERNAME XIDUSN UBAFIL UBABLK USED_UBLK
------- -------- ----------- ----------- -----------
SYSTEM 2 2 7 1
SCOTT 1 2 163 1
2 rows selected.
精确的回滚段的数量及大小的计算涉及很多方面:
2、OLAP系统/批处理系统应使用少量的大回滚段;每个事务一个回滚段。
3、OLTP/OLAP混合型系统中, 应专门设置一个或几个大的回滚段, 平时设置为OFFLINE, 使用时通过使用SET TRANSACTION USE ROLLBACK SEGMENT XXX来使用它。
4、所有的回滚段的INITIAL/NEXT参数应设为相同, 只有建议3中提到的大回滚段例外;
5、不要将回滚段的MAXEXTENTS设为UNLIMITED, 回滚段所在表空间也不要设为AUTOEXTEND方式, 否则将会使得由于某个不正常的事务导致整个数据库处于失控状态。
A. 回滚段所在表空间剩余的空闲空间太小, 无法分配下一个EXTENT.
B. 回滚段扩展次数已经达到MAXEXTENTS限制
解决方法:
A. 扩大回滚段所在表空间
B. 设置较大的MAXEXTENTS参数
C. 为回滚段设置OPTIMAL参数
D. 用较大的EXTENT参数重新创建回滚段
E. 将导致ORA-1562错误的DML语句改为分段执行:
(2) ORA-01552 cannot use system rollback segment for non-system tablespace 'string'
原因: 没有可用的非系统回滚段. 分为以下情形:
A. 除了系统回滚段, 未创建其它回滚段
B. 只创建了PRIVATE回滚段, 但INITsid.ORA的ROLLBACK_SEGMENTS中未列出这些回滚段
C. 创建了PUBLIC回滚段, 但这些回滚段都处于OFFLINE状态
A. 回滚段太少/太小
数据库中有太多的事务修改数据并提交, 就会发生已提交事务曾使用的空间被重用, 从而造成一个延续时间长的查询所请求的数据已经不在回滚段中.
解决方法: 创建更多的回滚段, 为回滚段设置较大的EXTENT以及较大的MINEXTENTS
B. 回滚段被破坏
由于回滚段被破坏, 造成事务无法将修改前的内容(read-consistent snapshot) 放入回滚段, 也会产生ORA-01555错误.
解决方法: 将被破坏的回滚段OFFLINE, 删除重建.
C. FETCH ACROSS COMMIT
当一个进程打开一个CURSOR, 然后循环执行FETCH, UPDATE, COMMIT, 如果更新的表与FETCH的是同一个表, 就很可能发生ORA-01555错误.
a. 使用大的回滚段
b. 减少提交频率
以上两种方法只能减少该错误发生的可能, 不能完全避免. 如果要完全避免, 须从执行方法着手, 可以用以下两种方法:
c. 建立一个临时表, 存放要更新的表的查询列(如主键及相关的条件列), 从临时表FETCH, 更新原来的表.
d. 捕获ORA-01555错误, 关闭并重新打开CURSOR, 继续执行循环:
示例(示例程序的思路来源自ORACLE的UTLIP.SQL, 有兴趣的朋友可直接阅读该程序, 位置在RDBMSADMIN下, 程序很短, 容易读):
DECLARE
LAST_PK NUMBER := 0;
V_THEROWID ROWID;
CURSOR C1 IS
SELECT ROWID, PK, ... FROM SMPLE
WHERE PK > LAST_PK
AND othercondition
ORDER BY PK;
BEGIN
OPEN c_SOURCE;
LOOP
BEGIN
FETCH C1 INTO v_THEROWID, v_PK;
EXIT WHEN C1%NOTFOUND;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -1555 THEN -- snapshot too old, re-execute fetch query
CLOSE C1;
OPEN c_SOURCE;
GOTO NEXTLOOP01555;
ELSE
RAISE;
END IF;
END;
LAST_PK := PK;
PROCESS,UPDATE AND COMMIT<>NULL;
END LOOP;
CLOSE C1;
END;