quinta-feira, 21 de janeiro de 2016
Corrupção física e lógica no Oracle
por Wagner Aparecido Miranda - W2R Consultoria e Sistemas
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 (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 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. Utilitário RMAN (Recovery Manager) ou;
2. Utilitário DB Verify – DBV
§ Utilizando o RMAN o paralelismo torna a validação mais rápida, porque utiliza vários canais.
§ 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.
Abaixo é apresentado o comando que verifica o banco de dados completo para ambas corrupções (lógica ou física) sem realmente executar uma cópia de segurança
RMAN> configure device type disk parallelism 4;
RMAN> backup validate check logical database;
ou
RMAN> 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]
blocksize = [tamanho_do_bloco_do_banco_de_dados]
Qual é o melhor? RMAN ou DBV?
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.
O DBV verifica a existência de blocos vazios. Então levará mais tempo para fazer a varredura de arquivo de dados inteiro.
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).
Na versão do Oracle 11g o RMAN verifica as extensões usadas e livres.
RMAN> VALIDATE DATAFILE 1 BLOCK 10 to 100;.
DBV> 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 v$ backup_corruption). O DBV não grava as informações de corrupção. As informações podem ser vistas utilizando a consulta abaixo.
Select * from v$database_block_corruption;
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
where file_id = &DATA_FILE_ID
and &CORRUPTED_BLOCK_ID
between block_id AND block_id + blocks - 1;
ou
SELECT e.owner, e.segment_type, e.segment_name, e.partition_name, c.file#
, greatest(e.block_id, c.block#) corr_start_block#
, least(e.block_id+e.blocks-1, c.block#+c.blocks-1) corr_end_block#
, least(e.block_id+e.blocks-1, c.block#+c.blocks-1)
- greatest(e.block_id, c.block#) + 1 blocks_corrupted
, null description
FROM dba_extents e, v$database_block_corruption c
WHERE e.file_id = c.file#
AND e.block_id <= c.block# + c.blocks - 1
AND e.block_id + e.blocks - 1 >= c.block#
UNION
SELECT s.owner, s.segment_type, s.segment_name, s.partition_name, c.file#
, header_block corr_start_block#
, header_block corr_end_block#
, 1 blocks_corrupted
, 'Segment Header' description
FROM dba_segments s, v$database_block_corruption c
WHERE s.header_file = c.file#
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#
, greatest(f.block_id, c.block#) corr_start_block#
, least(f.block_id+f.blocks-1, c.block#+c.blocks-1) corr_end_block#
, least(f.block_id+f.blocks-1, c.block#+c.blocks-1)
- greatest(f.block_id, c.block#) + 1 blocks_corrupted
, 'Free Block' description
FROM dba_free_space f, v$database_block_corruption c
WHERE f.file_id = c.file#
AND f.block_id <= c.block# + c.blocks - 1
AND f.block_id + f.blocks - 1 >= c.block#
order by file#, corr_start_block#;
Assinar:
Postagens (Atom)