【oracle11g,13】表空间管理2:undo表空间管理(调优),闪回原理(五)

2014-11-24 09:08:40 · 作者: · 浏览: 7
头(Segment Header)。这是由于并发DML操作引起的。这种情况表明段中的空闲列表(freelist)的块比较少。可以考虑增加空闲列表(freelist,对于Oracle8i DMT)或者增加freelist groups(在很多时候这个调整是立竿见影的(alter table tablename strorage(freelists 2)),在8.1.6之前,这个freelists参数不能动态修改;在8.1.6及以后版本,动态修改feelists需要设置COMPATIBLE至少为8.1.6)。也可以增加PCTUSED与PCTFREE之间距离(PCTUSED-to-pctfree gap),其实就是说降低PCTUSED的值,尽快使块返回freelist列表被重用。如果支持自动段空间管理(ASSM),也可以使用ASSM模式,这是在ORALCE 920以后的版本中新增的特性。

b) 如果这一等待位于undo header,说明多个事务使用同一个回滚段。可以通过增加回滚段(rollback segment)来解决缓冲区的问题。

c) 如果等待位于undo block上,我们需要增加提交的频率,使block可以尽快被重用;使用更大的回滚段;降低一致读所选择的表中数据的密度;增大DB_CACHE_SIZE。

d) 如果等待处于data block,表明出现了hot block,可能有多个事务访问同一个块的数据。可以考虑如下方法解决: ①将频繁并发访问的表或数据移到另一数据块或者进行更大范围的分布(可以增大pctfree值 ,扩大数据分布,减少竞争),以避开这个"热点"数据块。②也可以减小数据块的大小,从而减少一个数据块中的数据行数,降低数据块的热度,减小竞争;③检查对这些热块操作的SQL语句,优化语句。④增加hot block上的initrans值。但注意不要把initrans值设置的过于高了,通常设置为5就足够了。因为增加事务意味着要增加ITL事务槽,而每个ITL事务槽将占用数据块中24个字节长度。默认情况下,每个数据块或者索引块中是ITL槽是2个,在增加initrans的时候,可以考虑增大数据块所在的表的PCTFREE值,这样Oracle会利用PCTFREE部分的空间增加ITL slot数量,最大达到maxtrans指定。(select * from dba_tables,获取ini_trans,maxtrans,修改alter table tablename initrans 2)

e) 如果等待处于index block,应该考虑重建索引、分割索引或使用反向键索引。为了防止与数据块相关的缓冲忙等待,也可以使用较小的块,在这种情况下,单个块中的记录就较少,所以这个块就不是那么"繁忙"。或者可以设置更大的PCTFREE,使数据扩大物理分布,减少记录间的热点竞争。在执行DML (insert/update/ delete)时,Oracle向数据块中写入信息,对于多事务并发访问的数据表,关于ITL的竞争和等待可能出现,为了减少这个等待,可以增加initrans,使用多个ITL槽。在Oracle9i 中,可以使用ASSM这个新特性Oracle 使用位图来管理空间使用,减小争用。


②.Rollback per transaction
Rollback per transaction 如果很高,说明做了很多无用的事务。
SQL> select * from v$sysstat where name in ('user commits','user rollbacks','transaction rollbacks');
STATISTIC# NAME CLASS VALUE STAT_ID ---------- ------------------------- ---------- ---------- ---------- 4 user commits 1 5 582481098 5 user rollbacks 1 0 3671147913 187 transaction rollbacks 128 0 3988650402
4.回滚段的统计信息:

十一.如何产生较少的undo数据:

在export时,可以不设置consistent=n,但是要保证undo表空间足够大,防止export时产生的undo数据将undo占满,影响业务操作。
1.如何正确的插入数据:
①.一百条一提交,或者一千条一提交:
SQL> create table test(id number(8),name varchar2(30)); Table created.
SQL> begin 2 for i in 1..10000 loop 3 insert into test values(i,'zhangsan'||i); 4 if mod(i,1000)=0 then 5 commit; 6 end if; 7 end loop; 8 commit; 9 end; 10 /
PL/SQL procedure successfully completed.
②.一天一提交:
案例: #部署环境 SQL> create table emp_cu as select * from scott.emp; SQL> insert into emp_cu select * from emp_cu;
14 rows created.
SQL> /
28 rows created.
SQL> /
56 rows created.
SQL> /
112 rows created.
SQL> /
224 rows created.
SQL> /
448 rows created.
SQL> /
896 rows created.
SQL> commit; Commit complete. SQL> create index i_cu on emp_cu(empno); Index created.
#更新数据,用于下面的试验 SQL> declare cursor cu_emp is select * from emp_cu for update; 4 v_date date; 5 k number; 6 begin 7 k:=1; 8 v_date:=to_date('2010-01-01 08:00:00','yyyy-mm-dd HH24:MI:SS'); 9 for i in cu_emp loop 10 update emp_cu set hiredate=v_date,empno=k where current of cu_emp; 11 v_date:=v_date+1; 12 k:=k+1; 13 end loop; 14 commit; 15 end; 16 / 创建第二张表 SQL> create table emp_cu2 as select * from emp_cu where 1=2;
Table created. #建存储过程,将第一张表数据导到第二张表的 SQL> create or replace procedure proc_insert_data_t 2 as 3 current_time date; 4 begin 5 current_time:=to_date('2010-01-01 00:00:00','yyyy-mm-dd HH24:MI:SS'); 6 for count in 1..1000000 loop 7 insert into emp_cu2 8 select t.* from emp_cu t 9 where t.hiredate>=current_time 10 and t.hiredate=to_date('2015-01-01','yyyy-mm-dd'