Situação : Cliente liga reclamando que algumas consultas estão mais lentas que o normal. Até aí tudo bem.
E lá vou eu pro cliente pensando que ia resolver o problema com um pouquinho de dbms_stats, nosso amigos de sempre statspack/awr , talvez algum tkprof, além é claro da boa e velha v$session_wait.
No entanto a coisa tomou outro rumo quando achei um trace com os seguintes erros:
ORA-00600: internal error code, arguments: [2662], [2293], [1693171303], [6773], [2522013792], [16], [], []
ORA-08103: object no longer exists
Nesse momento,olho para o cliente que está ao meu lado (não fazendo pressão, mas investigando também claro
) e vejo aquela expressão de terror estampada na sua cara. Não demora muito e ele manda a pergunta crucial “Como assim tem um objeto que não existe mais ?”.
Após ter dado um tranqüilizante no cliente, fui tentar achar qual o objeto que não existia mais.
Consegui identificar o objeto e mandei o bom e velho analyze – o objeto aqui está com XXX por razões obvias.
SQL> analyze table XXX validate structure cascade;
analyze table XXX validate structure cascade
*
ERROR at line 1:
ORA-08103: object no longer exists
Confirmando com um select
SELECT ROWID, ultima_coluna_da_tabela from XXX
AAABz+AAHAAACDPAAp S
AAABz+AAHAAACDPAAq S
AAABz+AAHAAACDPAAr S
AAABz+AAHAAACDPAAs S
AAABz+AAHAAACDPAAt S
AAABz+AAHAAACDPAAu S
AAABz+AAHAAACDPAAv S
AAABz+AAHAAACDPAAw S
ERROR:
ORA-08103: object no longer exists
10073 rows selected.
Ok descobri qual o objeto e agora ?
Alguns detalhes.
Versão Oracle: 9.2.0.8 Standard 32bits Linux – Tabela em TS’s LMT.
Ao que parece isso é um resultado esperado se as tabelas estão sendo alvo de algum drop/truncate, enquanto consultas referenciando estas tabelas ainda estão sendo executados.
No caso de um index, o erro pode ter sido causado por um rebuild.
Colocando de maneira bem simples o objeto foi eliminado por outra sessão, enquanto a aplicação estava sendo executada.
- Nesse momento acho que vi um developer levantar e sair correndo…mas deve ter sido só impressão.
O fato é que o data_object_id (em dba_objects) foi alterado enquanto as consultas estavam rodando. Se não me engano , esta coluna pode mudar devido :
truncate table
alter index .. rebuild
alter table .. move
** Como internals: quando um truncate ocorre DATAOBJ# em OBJ$ aumenta de um e isso pode causar o ORA-08103.
Ah ! Isso também pode acontecer se o objeto estiver corrompido. Mas ai já é outra história
Voltando ao assunto do post vamos tentar simular o erro:
SQL> create table blah as select * from dual;
Tabela criada.
SQL> var c refcursor
SQL> begin open :c for select * from blah; end;
2 /
Procedimento PL/SQL concluído com sucesso.
SQL> drop table blah purge;
Tabela eliminada.
SQL> print c;
D
-
X
SQL>
No entanto se eu fizer o drop na tabela e re-utilizar este espaço (recriando outra tabela), o cursor vai falhar.
SQL> create table blah as select * from dual;
Tabela criada.
SQL> var c refcursor
SQL> begin open :c for select * from blah; end;
2 /
Procedimento PL/SQL concluído com sucesso.
SQL> drop table blah purge;
Tabela eliminada.
SQL> create table blah(a int); — este comando vai sobrescrever o header do bloco da tabela anterior
Tabela criada.
SQL> print c
ERROR:
ORA-08103: o objeto não existe mais
Não tem muito o que fazer não é ? O Objeto não existe mais. Fim da História.
E como ficou o cliente ? Ele ficou mais calmo depois que fiz um TSPITR com export e import desta tabela.