ORACLE 11G ORA-8103 错误问题处理一例
1.问题现象:
今天一朋友说他执行一个SQL语句,会报 ORA-08103错误,但选择其他字段不会:
select edit_time from ZLDOC.BZ_DOC_LOG where edit_time>sysdate-1;
ERROR at line 1:
ORA-08103: object no longer exists
2.问题分析:
使用
select creat_time from ZLDOC.BZ_DOC_LOG where creat_time>sysdate-1;
没有问题。
使用
select count(*) from ZLDOC.BZ_DOC_LOG,没有问题
导出数据
expdp \' / as sysdba\' directory=dbbak dumpfile=bz_doc_log.dmp logfile=tables.log tables=ZLDOC.BZ_DOC_Log 由于该表含有CLOB,XMLTYPE等类型,表数据只有20g,但对象有 280G,
所以,一直没有结果
使用 create table as select,会报ora-08103 错误。
3.联机文档解释:
ORA-08103: object no longer exists
Cause: The object has been deleted by another user since the operation began, or a prior incomplete recovery restored the database to a point in time during the deletion of the object.
Action: Delete the object if this is the result of an incomplete recovery.
ORA-08103表示在进行持久操作时找不到某个对象,具体地说,就是表或视图不能因为已经丢失或被删除,但是还有指向它的对象的句柄。在开发数据库过程中,很可能会碰到这个错误,这个错误是由于表或视图被删除或不存在,但是SQL查询还是链接到该表或视图。
4.网上的解决办法:
1.转到SYSDBA模式,连接到数据库,查看表的具体信息;
2.查看表的对象是否存在,确定表是否存在;
3.如果表不存在,要查看用户正在尝试查询哪些表,以及出现ORA-08103错误的表是哪个;
4.查看相关联的语句,调查是否有第三方程序和进程正在尝试访问ORA-08103的表;
5.查看系统中的脚本是否有问题,以及更改现有脚本来访问ORA-08103的表;
6.重新创建被删除的表,并执行必要的记录操作,重新测试语句,以确保它正确地表示被访问的表;
7.正确地应用 Oracle 支持的可选特征,以防止Oracle 数据库出现ORA-08103错误;
8.重新创建该表,重新运行SELECT语句,重新获取该表,以更正ORA-08103错误。
看起来不太靠谱,这个表含大对象有280G,不太好重建,而且我们重建也会报同样的错。
5.通过 mos:1527738.1所提供的脚本去保存好的记录,运行一段,就失败了,报:ORA-03113的错误
6.确定问题块
搜MOS,根据 Doc ID 1671518.1 跟踪SQL语句
alter session set max_dump_file_size=unlimited;
alter session set db_file_multiblock_read_count=1;
alter session set events 'immediate trace name trace_buffer_on level 1048576';
alter session set events '10200 trace name context forever, level 1';
alter session set events '10236 trace name context forever, level 1';
alter session set events '8103 trace name errorstack level 3';
alter session set tracefile_identifier='ORA8103';
----->>>> run the sql statement that causes the ORA-08103
alter session set events 'immediate trace name trace_buffer_off';
oradebug setmypid
oradebug tracefile_name
发现了错误的块是 8/2922345:
。。。
BH (0x20f664288) file#: 8 rdba: 0x022c9769 (8/2922345) class: 1 ba: 0x200006000
set: 171 pool: 3 bsz: 8192 bsi: 0 sflg: 1 pwc: 3690,28
dbwrid: 2 obj: 87376 objn: 87376 tsn: 9 afn: 8 hint: f
hash: [0x109fca6ef8,0xf9f83efb8] lru: [0x104f678dc0,0x104f6724f0]
ckptq: [NULL] fileq: [NULL] objq: [0xcfc639f8,0xfef758a98] objaq: [0x100f710fd0,0x122f713808]
use: [NULL] wait: [NULL] fast-cr-pins: 1
st: XCURRENT md: NULL fpin: 'ktspbwh2: ktspfmdb' tch: 161
flags: block_written_once redo_since_read
LRBA: [0x0.0.0] LSCN: [0x0.0] HSCN: [0xffff.ffffffff] HSUB: [1]
buffer tsn: 9 rdba: 0x00000000 (0/0)
scn: 0x0000.00000000 seq: 0x00 flg: 0x00 tail: 0x220a0601
frmt: 0x00 chkval: 0x0000 type: 0x00=unknown
Hex dump of corrupt header 4 = CORRUPT
。。。
通过ROWID,保留 坏块:
create table bad_rows_SAMPLE (row_id rowid, oracle_error_code number);
set serveroutput on
declare
n number;
error_code number;
bad_rows number := 0;
e_time date;
ora1578 EXCEPTION;
ora600 EXCEPTION;
ora8103 EXCEPTION;
PRAGMA EXCEPTION_INIT(ora1578, -1578);
PRAGMA EXCEPTION_INIT(ora600, -600);
PRAGMA EXCEPTION_INIT(ora8103, -8103);
begin
for cursor_lob in (select rowid rid from ZLDOC.BZ_DOC_LOG ) loop
begin
select edit_time into e_time from ZLDOC.BZ_DOC_LOG where rowid=cursor_lob.rid ;
exception
when ora8103 then
bad_rows := bad_rows + 1;
insert into bad_rows_SAMPLE values(cursor_lob.rid,8103);
commit;
when ora1578 then
bad_rows := bad_rows + 1;
insert into bad_rows_SAMPLE values(cursor_lob.rid,1578);
commit;
when ora600 then
bad_rows := bad_rows + 1;
insert into bad_rows_SAMPLE values(cursor_lob.rid,600);
commit;
when others then
error_code:=SQLCODE;
bad_rows := bad_rows + 1;
insert into bad_rows_SAMPLE values(cursor_lob.rid,error_code);
commit;
end;
end loop;
dbms_output.put_line('Total Rows identified with errors in LOB column: '||bad_rows);
end;
/
SQL> select * from bad_rows_SAMPLE;
ROW_ID ORACLE_ERROR_CODE
------------------ -----------------
AAAVVQAAIAALJdpAAA 8103
AAAVVQAAIAALJdpAAB 8103
AAAVVQAAIAALJdpAAC 8103
AAAVVQAAIAALJdpAAD 8103
AAAVVQAAIAALJdpAAE 8103
AAAVVQAAIAALJdpAAF 8103
AAAVVQAAIAALJdpAAG 8103
AAAVVQAAIAALJdpAAH 8103
AAAVVQAAIAALJdpAAI 8103
AAAVVQAAIAALJdpAAV 8103
AAAVVQAAIAALJdpAAJ 8103
ROW_ID ORACLE_ERROR_CODE
------------------ -----------------
AAAVVQAAIAALJdpAAK 8103
AAAVVQAAIAALJdpAAL 8103
AAAVVQAAIAALJdpAAM 8103
AAAVVQAAIAALJdpAAN 8103
AAAVVQAAIAALJdpAAO 8103
AAAVVQAAIAALJdpAAP 8103
AAAVVQAAIAALJdpAAQ 8103
AAAVVQAAIAALJdpAAR 8103
AAAVVQAAIAALJdpAAS 8103
AAAVVQAAIAALJdpAAT 8103
AAAVVQAAIAALJdpAAa 8103
ROW_ID ORACLE_ERROR_CODE
------------------ -----------------
AAAVVQAAIAALJdpAAU 8103
AAAVVQAAIAALJdpAAW 8103
AAAVVQAAIAALJdpAAX 8103
AAAVVQAAIAALJdpAAY 8103
AAAVVQAAIAALJdpAAZ 8103
AAAVVQAAIAALJdpAAb 8103
已选择28行。
SQL> r
1 select row_id,dbms_rowid.rowid_object(row_id) "#object",
2 dbms_rowid.rowid_relative_fno(row_id) "#file",
3 dbms_rowid.rowid_block_number(row_id) "#block",
4 dbms_rowid.rowid_row_number(row_id) "#row"
5 from bad_rows_SAMPLE
6 order by 1
7*
ROW_ID #object #file #block #row
------------------ ---------- ---------- ---------- ----------
AAAVVQAAIAALJdpAAA 87376 8 2922345 0
AAAVVQAAIAALJdpAAB 87376 8 2922345 1
AAAVVQAAIAALJdpAAC 87376 8 2922345 2
AAAVVQAAIAALJdpAAD 87376 8 2922345 3
AAAVVQAAIAALJdpAAE 87376 8 2922345 4
AAAVVQAAIAALJdpAAF 87376 8 2922345 5
AAAVVQAAIAALJdpAAG 87376 8 2922345 6
AAAVVQAAIAALJdpAAH 87376 8 2922345 7
AAAVVQAAIAALJdpAAI 87376 8 2922345 8
AAAVVQAAIAALJdpAAJ 87376 8 2922345 9
AAAVVQAAIAALJdpAAK 87376 8 2922345 10
ROW_ID #object #file #block #row
------------------ ---------- ---------- ---------- ----------
AAAVVQAAIAALJdpAAL 87376 8 2922345 11
AAAVVQAAIAALJdpAAM 87376 8 2922345 12
AAAVVQAAIAALJdpAAN 87376 8 2922345 13
AAAVVQAAIAALJdpAAO 87376 8 2922345 14
AAAVVQAAIAALJdpAAP 87376 8 2922345 15
AAAVVQAAIAALJdpAAQ 87376 8 2922345 16
AAAVVQAAIAALJdpAAR 87376 8 2922345 17
AAAVVQAAIAALJdpAAS 87376 8 2922345 18
AAAVVQAAIAALJdpAAT 87376 8 2922345 19
AAAVVQAAIAALJdpAAU 87376 8 2922345 20
AAAVVQAAIAALJdpAAV 87376 8 2922345 21
ROW_ID #object #file #block #row
------------------ ---------- ---------- ---------- ----------
AAAVVQAAIAALJdpAAW 87376 8 2922345 22
AAAVVQAAIAALJdpAAX 87376 8 2922345 23
AAAVVQAAIAALJdpAAY 87376 8 2922345 24
AAAVVQAAIAALJdpAAZ 87376 8 2922345 25
AAAVVQAAIAALJdpAAa 87376 8 2922345 26
AAAVVQAAIAALJdpAAb 87376 8 2922345 27
已选择28行。
通过这个块分析,发现有问题的块,就是块 2922345 和上面 8103跟踪的相对应。
7.各种想法尝试
看来这个块有问题,单独去执行
select id from ZLDOC.BZ_DOC_LOG where rowid='AAAVVQAAIAALJdpAAb';
都会报 ora-8103
create index idx_doc_log on ZLDOC.BZ_DOC_LOG(edit_time);同样报错
不想要这28条记录,
delete from ZLDOC.BZ_DOC_LOG where rowid in (select row_id from bad_rows_SAMPLE);
也会报 ora-8103
本来想放弃这个28行,保存好的记录:
declare
n number;
error_code number;
bad_rows number := 0;
e_time date;
ora1578 EXCEPTION;
ora600 EXCEPTION;
ora8103 EXCEPTION;
PRAGMA EXCEPTION_INIT(ora1578, -1578);
PRAGMA EXCEPTION_INIT(ora600, -600);
PRAGMA EXCEPTION_INIT(ora8103, -8103);
begin
for cursor_lob in (select rowid rid from ZLDOC.BZ_DOC_LOG ) loop
begin
insert into ZLDOC.BZ_DOC_LOG_Norm select /*+ ROWID(A) */ * from ZLDOC.BZ_DOC_LOG A where rowid=cursor_lob.rid ;
exception
when ora8103 then
bad_rows := bad_rows + 1;
insert into bad_rows_SAMPLE values(cursor_lob.rid,8103);
commit;
when ora1578 then
bad_rows := bad_rows + 1;
insert into bad_rows_SAMPLE values(cursor_lob.rid,1578);
commit;
when ora600 then
bad_rows := bad_rows + 1;
insert into bad_rows_SAMPLE values(cursor_lob.rid,600);
commit;
when others then
error_code:=SQLCODE;
bad_rows := bad_rows + 1;
insert into bad_rows_SAMPLE values(cursor_lob.rid,error_code);
commit;
end;
end loop;
dbms_output.put_line('Total Rows identified with errors in LOB column: '||bad_rows);
end;
/
这个很快就会报0RA-03113的错误,没有看到好的解释,有点奇怪 ,看来想保存好的数据,都存在问题。
看来这样搞,还是有问题,
继续网上搜,发现一个方法,可以把 8103变成真正的坏块,然后再跳过这些坏块。
在bbed设置坏块看看.
BBED> set dba 8,2922345
DBA 0x022c9769 (25166083 8,2922345)
BBED> corrupt
Block marked media corrupt.
BBED> sum apply ;
Check value for File 8, Block 2922345:
current = 0xa683, required = 0xa683
SQL>ALTER SESSION SET EVENTS '10231 TRACE NAME CONTEXT FOREVER, LEVEL 10';
8.最终解决
但想到按这样处理,就要丢数据了.
但真的没有办法了吗
还是不太甘心,中午了,想到还是要赶紧把这个问题处理了,再去吃饭,再网上搜了一些,看到有人,直接把数据缓冲去刷一下,就可以了
想到已经是13:00,现在用的人少,赶紧试一下,
alter system flush buffer_cache;
再去看原来要报错的地方:
select edit_time from ZLDOC.BZ_DOC_LOG where edit_time>sysdate-1;
尽然真的不报错了,
赶紧看看直接有报错的块,
select id,edit_time from ZLDOC.BZ_DOC_LOG where rowid in (select row_id from bad_rows_SAMPLE);
确实不报错了
再让朋友检查应用,说修改时间不报错了,但创建时间要报错了,
听到这里,吓我一跳,难倒还有问题,让对方把错误图片贴一个出来,结果是报 " ORA-00920 无效的关系运算符", 明显是SQL语句的问题,让对方看一下,结果是对方SQL语句搞掉了一段。重新运行,问题解决。
到这里,问题已经解决。
9.反思
但反过来想,怎么最终这么简单的问题,最后,花了这么多功夫呢,可能还是被网络误导了,看到网络上都把这个问题夸大了,导致一心也想到问题不会很简单,需要使用高大上的工具才能解决,反而把自己带偏了。
后来,回过头来再次搜MOS,结果上面本来就有一篇文章:
Query from subscriber errors with Ora-8103 (Doc ID 1365868.1)
这个文章说了原因,以及给了一个链接:
OERR: ORA-8103 "object no longer exists" / Troubleshooting, Diagnostic and Solution (Doc ID 8103.1)
这篇文章中,说了各种可能,里面就有一个说可能只在BUFFER CACHE 存在损坏,直接刷一下缓冲区即可
看来这次问题处理,确实是事情多了,简单的问题,复杂化了。
今后解决问题,首先还是要相信官方的知识库.
最后感谢:DBA 札记1群的群主,及小伙伴们,谢谢你们提供思路,让我快速找到问题的解决之道。
参考文档:
ORA-08103: Object No Longer Exists (Doc ID 1465978.1)
SRDC - Required Diagnostic Data Collection for ORA-08103 (Doc ID 1671518.1)
OERR: ORA-8103 "Object No Longer Exists" Primary Note / Troubleshooting, Diagnostic and Solution (Doc ID 8103.1)
|