- 最后登录
- 2018-4-3
- 在线时间
- 11 小时
- 威望
- 0
- 金钱
- 79
- 注册时间
- 2016-8-31
- 阅读权限
- 10
- 帖子
- 3
- 精华
- 0
- 积分
- 0
- UID
- 2480
|
1#
发表于 2016-8-31 20:48:57
|
查看: 3330 |
回复: 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
|
|