Corrupção física e lógica no Oracle
Autor: Wagner Aparecido Miranda | Publicado: 2016-01-21T04:51:00-08:00



por Wagner Aparecido Miranda -&nbsp;W2R Consultoria e Sistemas&nbsp;


Este artigo relata um fato vivido recentemente em Cliente.

Primeiro vamos aos conceitos:

O que é uma corrupção física?

Um bloco pode estar corrompido se o “CHECKSUM” estiver inválido. E quando isso pode ocorrer?

Quando o cabeçalho do bloco estiver inválido - ocorre início do bloco está corrompido com valores inválidos.

Quando o bloco estiver incompleto – ocorre quando as informações do cabeçalho do bloco não correspondem com o restante do bloco (conhecido também como cauda de bloco).

Quando CHECKSUM estiver inválido – o &nbsp;(CHECKSUM) é calculado pelo processo (DBWR) ou pelo processo (direct loader) antes de gravar o bloco do disco e armazenar o cabeçalho do bloco.

O parâmetro &nbsp;DB_BLOCK_CHECKSUM pode ser usado para identificar se o bloco foi alterado por algo externo ao banco de dados e também para depois que o bloco foi gravado pela última vez pelo banco de dados. Toda vez que o bloco é lido e se o parâmetro DB_BLOCK_CHECKSUM estiver diferente de FALSE, o banco de dados calcula o CHECKSUM e compara a informação armazenada no cabeçalho do bloco.

Blocos deslocados – ocorrec quando o banco de dados Oracle detecta que o conteúdo do bloco a ser lido pertence a um bloco diferente e o CHECKSUM é válido. A corrupção de blocos físicos, normalmente são relatados como erros ORA-1578 e a descrição detalhada da corrupção é gravada no arquivo do “alert.log”.

O que é uma corrupção lógica?

Quando o bloco contém a verificação do CHECKSUM válida e a estruturado início do bloco está corrompida (o conteúdo do bloco está corrompido).

Corrupções lógicas não são normalmente gravadas no alert.log. O utilitário DBVerify apresenta os blocos que estão logicamente danificados no bloco.

Quando o parâmetro DB_BLOCK_CHECKING está habilitado, ele grava o erro interno ORA-600 [kddummy_blkchk].

Se o parâmetro DB_BLOCK_CHECKING estiver habilitado e o bloco já estiver logicamente corrompido no disco, a próxima atualização do bloco irá marcar o bloco como “Soft Corrupt” e futuras leituras deste bloco irão produzir o erro ORA-1578. Nesse caso o utilitário DBVerify apresenta a corrupção com o erro "DBV-200: Block, dba, already marked corrupted".

Como identificar os segmentos corrompidos no banco de dados?

Para identificar tanto o dano físico como lógico pode usar:

1. &nbsp; Utilitário RMAN (Recovery Manager) ou;

2. &nbsp; Utilitário DB Verify – DBV

§ &nbsp;Utilizando o RMAN o paralelismo torna a validação mais rápida, porque utiliza vários canais.

§ &nbsp;Por “default” os backups via RMAN (não possuem a opção de verificação lógica) só existe a detecção de corrupções de bloco físico.&nbsp;

Abaixo é apresentado o comando que verifica o banco de dados completo para ambas corrupções (lógica ou física) sem realmente executar &nbsp;uma cópia de segurança

RMAN&gt; configure device type disk parallelism 4;
RMAN&gt; backup validate check logical database;

ou

RMAN&gt; run {
allocate channel diskl1 type disk;
allocate channel disk2 type disk;
allocate channel disk3 type disk;
allocate channel disk4 type disk;
backup validate check logical database;
}


Como identificar corrupção física ou lógica utilizando o utilitário DBVerify?

O utilitário DBVERIFY identifica corrupções físicas e lógicas, porém esse utilitário não pode ser executado no banco de dados inteiro utilizando somente um único comando. Para executá-lo não é necessário conexão com o banco de dados.

Deve-se indicar cada “datafile”, como no exemplo abaixo:

$ dbv file=[caminho+nome_do_datafile]
&nbsp; &nbsp; &nbsp; blocksize = [tamanho_do_bloco_do_banco_de_dados]


Qual é o melhor? RMAN ou DBV?

&nbsp; O RMAN pode ser executado com a opção de paralelismo, tornando-o mais rápido que o DBV que não pode ser executado em paralelo.
&nbsp; O DBV verifica a existência de blocos vazios. Então levará mais tempo para fazer a varredura de arquivo de dados inteiro.
&nbsp; Na versão do Oracle 10g o RMAN não pode marcar blocos com extensões livres quando estejam configuradas em LMT (Locally Managed Tablespaces).
&nbsp; Na versão do Oracle 11g o RMAN verifica as extensões usadas e livres.
&nbsp; &nbsp; &nbsp;RMAN&gt; VALIDATE DATAFILE 1 BLOCK 10 to 100;.&nbsp;

DBV&gt; start=10 end=100

O RMAN mantém as informações de corrupção no arquivo de control file (nas visões: v$ database_block_corruption e &nbsp;v$ backup_corruption). O &nbsp;DBV não grava as informações de corrupção. As informações podem ser vistas utilizando a consulta abaixo.

&nbsp; &nbsp; Select * from v$database_block_corruption;

&nbsp;O RMAN não grava detalhes de corrupção como o que exatamente está corrompido em um bloco relatado como uma lógica bloco corrompido.O DBV relata os detalhes de corrupção na tela ou em um arquivo de log.
O DBV pode digitalizar blocos com um SCN mais elevado do que um determinado SCN.
O DBV não precisa de uma conexão com o banco de dados.

select * from dba_extents
&nbsp;where file_id = &amp;DATA_FILE_ID
&nbsp; &nbsp;and &amp;CORRUPTED_BLOCK_ID&nbsp;
&nbsp; &nbsp; between block_id AND block_id + blocks - 1;

ou

SELECT e.owner, e.segment_type, e.segment_name, e.partition_name, c.file#
&nbsp; &nbsp; &nbsp;, greatest(e.block_id, c.block#) corr_start_block#
&nbsp; &nbsp; &nbsp;, least(e.block_id+e.blocks-1, c.block#+c.blocks-1) corr_end_block#
&nbsp; &nbsp; &nbsp;, least(e.block_id+e.blocks-1, c.block#+c.blocks-1)
&nbsp; &nbsp; &nbsp; &nbsp;- greatest(e.block_id, c.block#) + 1 blocks_corrupted
&nbsp; &nbsp; &nbsp;, null description
&nbsp; FROM dba_extents e, v$database_block_corruption c
&nbsp;WHERE e.file_id = c.file#
&nbsp; &nbsp;AND e.block_id &lt;= c.block# + c.blocks - 1
&nbsp; &nbsp;AND e.block_id + e.blocks - 1 &gt;= c.block#
UNION
SELECT s.owner, s.segment_type, s.segment_name, s.partition_name, c.file#
&nbsp; &nbsp; &nbsp;, header_block corr_start_block#
&nbsp; &nbsp; &nbsp;, header_block corr_end_block#
&nbsp; &nbsp; &nbsp;, 1 blocks_corrupted
&nbsp; &nbsp; &nbsp;, 'Segment Header' description
&nbsp; FROM dba_segments s, v$database_block_corruption c
&nbsp;WHERE s.header_file = c.file#
&nbsp; &nbsp;AND s.header_block between c.block# and c.block# + c.blocks - 1
UNION
SELECT null owner, null segment_type, null segment_name, null partition_name, c.file#
&nbsp; &nbsp; &nbsp;, greatest(f.block_id, c.block#) corr_start_block#
&nbsp; &nbsp; &nbsp;, least(f.block_id+f.blocks-1, c.block#+c.blocks-1) corr_end_block#
&nbsp; &nbsp; &nbsp;, least(f.block_id+f.blocks-1, c.block#+c.blocks-1)
&nbsp; &nbsp; &nbsp; &nbsp;- greatest(f.block_id, c.block#) + 1 blocks_corrupted
&nbsp; &nbsp; &nbsp;, 'Free Block' description
&nbsp; FROM dba_free_space f, v$database_block_corruption c
&nbsp;WHERE f.file_id = c.file#
&nbsp; &nbsp;AND f.block_id &lt;= c.block# + c.blocks - 1
&nbsp; &nbsp;AND f.block_id + f.blocks - 1 &gt;= c.block#
order by file#, corr_start_block#;