Oracle数据库数据恢复、性能优化

找回密码
注册
搜索
热搜: 活动 交友 discuz
发新帖

0

积分

1

好友

1

主题
1#
发表于 2016-8-31 20:48:57 | 查看: 3329| 回复: 1
背景:最近生产发生了15555错误 DBA直接扩了undo空间 解决了,但是我还是想系统了解一下15555实际原因
自己测试了一下 也重现了该问题。但是有两点疑问始终没有理解。请刘大和其他大神帮忙解答一下我的相关疑问,多谢了!!
测试环境数据准备
create undo tablespace undo_small datafile '/s01/oradata/DBDAO/undotest02.dbf' size 10m autoextend off;
alter system set undo_tablespace = undo_small;
create table undotest as select * from all_objects;
create index t_idx on undotest(object_name);
exec dbms_stats.gather_table_stats(user,'UNDOTEST',cascade => true);
declare
cursor cc is
select /*+ index(undotest t_idx) */rowid rid,object_name,rownum r,object_id from undotest where object_name>' ';
l_rownum number:=0;
v_rwd   rowid;
--l_rowcnt  number:=0;
v_objname undotest.object_name%type;
v_objid undotest.object_id%type;
v_oobjid undotest.object_id%type;
begin
  --for x in(select /*+ index(undotest t_idx) */rowid rid,object_name,rownum r from undotest where object_name>' ')
    open cc;
    loop
       v_objid :=0;
       fetch cc into v_rwd,v_objname,l_rownum,v_objid;
       v_oobjid :=v_objid;
       update undotest set object_name=lower(v_objname)where rowid=v_rwd;
       if (mod(l_rownum,100)=0) then
       commit;
       end if;
    end loop;
    ---commit;
    exception
       when others then
          commit;
          dbms_output.put_line('rows fetched = '||l_rownum||'objname='||v_objname||'old='||v_oobjid||'objid='||v_objid);
          raise;
end;

rows fetched = 69231objname=WWV_AIU_FND_USERold=85239objid=0
declare
*
ERROR at line 1:
ORA-01555: snapshot too old: rollback segment number 22 with name
"_SYSSMU22_3344022324$" too small
ORA-06512: at line 27
有几点疑问:
1.上面游标FETCH的时候怎么会发生一致性读呢?
个人理解是这样的:上面的 update语句是通过rowid去更新 每次肯定只更新一行(如果有误请指出),那么下次再FETCH的时候就不会再fetch已经更新的那行数据了吧?
如果还会FETCH到原来的数据,它又是怎么FETCH到原来的数据的呢?难道"一个游标在每次FETCH记录的时候 内部是通过select 语句去再次查询我的测试表吗?"

2.我现在想验证是由于查询哪个块的哪条记录的一致性读或者延迟块清除 导致 ORA-01555 该如何处理?
我的方法如下:
1)按照上面建表语句重新建一个表
create table undotest1 as select * from all_objects where object_name<>'UNDOTEST';
create index t_idx1 on undotest1(object_name);
  exec dbms_stats.gather_table_stats(user,'UNDOTEST1',cascade => true);
  比较两个表的数据
  SQL> select count(*) from undotest1;

  COUNT(*)
----------
     85017

SQL> select count(*) from undotest;

  COUNT(*)
----------
     85016
找到理论的FETCH报错的那个OBJECT_ID
select * from ( select * from (select /*+ index(undotest1 t_idx1) */rowid rid,object_name,rownum r,object_id from undotest1 where object_name>' ')where object_name='WWV_AIU_FND_USER')where rownum=1;

RID                   OBJECT_NAME                                   R  OBJECT_ID
------------------ ------------------------------ ---------- ----------
AAAV4VAAGAAACYtABA WWV_AIU_FND_USER                       69232          85239

SQL> select * from ( select * from (select /*+ index(undotest1 t_idx1) */rowid rid,object_name,rownum r,object_id from undotest1 where object_name>' ')where r=69233) where rownum=1;

RID                   OBJECT_NAME                                   R  OBJECT_ID
------------------ ------------------------------ ---------- ----------
AAAV4VAAGAAACYsAAq WWV_BD_FLOWCOMPUTATIONS               69233          85150

查询理论的FETCH报错的那个OBJECT_ID 所在的块
select object_id,dbms_rowid.rowid_block_number(rowid) blk,dbms_rowid.rowid_relative_fno(rowid) fno from undotest where object_id in(85239,85150);

OBJECT_ID          BLK             FNO
---------- ---------- ----------
     85150         5164               6
     85239         5165               6
     
alter system dump datafile 6 block 5164;
alter system dump undo header '_SYSSMU22_3344022324$';

数据块的dump文件
Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 0x0000.003b28b3
0x02   0x0016.013.0000043a  0x024002f2.00cd.30  --U-    1  fsc 0x0000.003b4f2f
0x03   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
省略部分
tab 0, row 7, @0x1c46
tl: 88 fb: --H-FL-- lb: 0x2  cc: 14
col  0: [11]  41 50 45 58 5f 30 33 30 32 30 30
col  1: [ 6]  61 70 65 78 77 73
col  2: *NULL*
col  3: [ 4]  c3 09 34 10
col  4: *NULL*
col  5: [ 7]  50 41 43 4b 41 47 45
col  6: [ 7]  78 71 08 18 0c 3b 25
col  7: [ 7]  78 71 08 18 0d 03 19
但是我发现这里未被清除的锁标志的行号的记录并不是我们的WWV_BD_FLOWCOMPUTATIONS
所以我该如何去验证到底是由于哪个块的一致性读导致ORA-01555

alert日志由错误信息如下:
  Tue Aug 30 10:25:00 2016
ORA-01555 caused by SQL statement below (SQL ID: fbtd7gjq9gw9z, Query Duration=70 sec, SCN: 0x0000.003ad814):
SELECT /*+ index(undotest t_idx) */ROWID RID,OBJECT_NAME,ROWNUM R,OBJECT_ID FROM UNDOTEST WHERE OBJECT_NAME>' '
Tue Aug 30 10:25:00 2016
error 376 happened for queue:IX.STREAMS_QUEUE_TABLE during timed act
Errors in file /s01/diag/rdbms/dbdao/DBDAO/trace/DBDAO_mmon_2544.trc  (incident=146564):
ORA-25319: Queue table repartitioning aborted
error 25319 happened during Queue table repartitioning
2#
发表于 2016-8-31 20:51:36
问题可能很low,还请大神们见谅

回复 只看该作者 道具 举报

您需要登录后才可以回帖 登录 | 注册

QQ|手机版|Archiver|Oracle数据库数据恢复、性能优化

GMT+8, 2024-12-20 15:33 , Processed in 0.047463 second(s), 21 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部
TEL/電話+86 13764045638
Email service@parnassusdata.com
QQ 47079569