Erro na coleta de estatística devido a corrupção lógica de dados - (ORA-07445 [evadmp()+686] [SIGSEGV] [ADDR:0x0])

Durante a coleta de estatística do ambiente, identificamos que o processo estava sendo abortado depois de algumas horas em execução.

Na sessão que estava sendo executada tínhamos apenas o erro de que conexão havia sido abortada e os erros abaixo eram gravados no alertlog.
  • Erro da sessão:
SQL> execute dbms_stats.gather_table_stats(ownname=>'OWNER',tabname=>'CONFIGURACOES');
BEGIN dbms_stats.gather_table_stats(ownname=>'OWNER',tabname=>'CONFIGURACOES'); END;

*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 7736
Session ID: 7 Serial number: 26973
  • Principais erros gravados no alertlog ao executar a coleta de estatística da tabela em questão:
ORA-00600: internal error code, arguments: [kghrcdepth:ds], [0x7F14B30E2008], [], [], [], [], [], [], [], [], [], []
ORA-07445: exception encountered: core dump [kgherrordmp()+986] [SIGSEGV] [ADDR:0x0] [PC:0x7B545D0] [Address not mapped to object] []
ORA-00600: internal error code, arguments: [17114], [0x7F14B30E0FC8], [], [], [], [], [], [], [], [], [], []
ORA-00600: internal error code, arguments: [qksanAnalyzeSql:xsc2], [0x7FFF06094BB8], [0x7F14B30A9148], [], [], [], [], [], [], [], [], []
ORA-06512: at "SYS.DBMS_STATS", line 24232
ORA-06512: at "SYS.DBMS_STATS", line 24332
ORA-06512: at line 1
ORA-07445: exception encountered: core dump [evadmp()+686] [SIGSEGV] [ADDR:0x0] [PC:0x200611A] [SI_KERNEL(general_protection)] []

Este erro ocorre devido a existência de colunas com dados que possuam mais caracteres do que o limite da coluna. Por exemplo uma coluna com 40 caracteres, sendo que o campo esta definido com varchar2(30).

A Oracle disponibiliza um script para validação de dados corrompidos a nível de coluna, através da Doc ID 428526.1. Também estou disponibilizando o mesmo através do link a seguir: baddata.sql.

Para executa-lo precisaremos de acesso com o owner SYS.
SQL> show user;
USER is "SYS"
SQL>

SQL> @baddata.sql

Package body dropped.

Package dropped.

PL/SQL procedure successfully completed.

Table created.

Index created.

0 rows deleted.

1 row created.

1 row created.

1 row created.

1 row created.

1 row created.

1 row created.

1 row created.

Commit complete.

Package created.

Package body created.

-- Object SCOTT.EMP not found !!!

PL/SQL procedure successfully completed.

SQL>
Após criada a estrutura com a execução do script baddata.sql, será realizada a verificação através da package BADDATA.
Esta package possuí opção para validação do banco inteiro, de um schema inteiro ou de uma tabela. Ainda é possível através da opção dochars ignorar a validação de campos CHAR/VARCHAR2, definindo o valor da mesma para false.

Para validação do banco inteiro, usamos:  BadData.CheckDB( DoChars=>TRUE ); -- Apenas lembrando que esta opção poderá demorar bastante, uma vez que fará uma validação de todas tabelas do banco.

Para validação de um schema específico, usamos: BadData.CheckSchema('SCHEMANAME', DoChars=>TRUE);.

E para validação de uma tabela específica: BadData.CheckObject('SCHEMANAME','TABLENAME',DoChars=>TRUE);.

Abaixo será demonstrada a execução para uma tabela específica.
SQL> show user;
USER is "SYS"
SQL> spool mybaddata.log
SQL> execute dbms_output.enable(1000000);

PL/SQL procedure successfully completed.

SQL> set serveroutput on;
SQL> begin
        BadData.CheckObject('OWNER','CONFIGURACOES',DoChars=>TRUE);
end;
/  2    3    4
REM OWNER.CONFIGURACOES has 9 suspect rows
rem Column DT_SYNCRO_ has 9 Bad DATE
REM
REM Use this SQL to see the bad row/s:
SELECT TAB.rowid
,dump("CONFIGURACAO_O")
,dump("DT_SYNCRO_")
,dump("SYNC_UPD")
,dump("SYNCRO_")
,dump("USUARIO_O")
,dump("CONFIGURACAO")
,dump("USUARIO")
,dump("VALOR")
FROM "OWNER"."CONFIGURACOES" TAB WHERE (
(nvl(length("CONFIGURACAO_O"),0)>100)
OR ("DT_SYNCRO_"!="DT_SYNCRO_"+0)
OR (nvl(length("SYNC_UPD"),0)>1)
OR ("SYNCRO_"!="SYNCRO_"/1)
OR (nvl(length("USUARIO_O"),0)>20)
OR (nvl(length("CONFIGURACAO"),0)>100)
OR (nvl(length("USUARIO"),0)>40)
OR (nvl(length("VALOR"),0)>100) )
;

PL/SQL procedure successfully completed.

SQL>
Conforme validação do script, foram identificadas 9 linhas com campo data que possuem valores incorretos. Para mais detalhes, basta executar o SQL gerado.
Neste exemplo, podemos ver que o campo dt_syncro_ possuí o tamanho de 11 bytes. Porém o campo date deve ter um tamanho fixo de 7 bytes, conforme a documentação.

Imagem da consulta executada através do SQL Developer:


Documentação:
Outra validação que pode ser feita após descobrir a tabela é um create table as select. Ele também apresentará erro devido a um valor ser maior do que o limite para a coluna.
SQL> create table lamim.teste as select * from OWNER.CONFIGURACOES;
create table lamim.teste as select * from OWNER.CONFIGURACOES
                                   *
ERROR at line 1:
ORA-12899: value too large for column ??? (actual: 11, maximum: 7)


SQL>
Agora que foram descobertas as linhas com corrupção, as mesmas precisam ser corrigidas ou removidas. Feito isso a coleta executará com sucesso.

Fonte:
ORA-07445: Exception Encountered: Core Dump [evadmp()+686] (Doc ID 1528920.1)
Baddata Script To Check Database For Corrupt column data (Doc ID 428526.1)

Comentários