Durante a execução de um backup full database(RMAN) obtive o erro ORA-19566 informando a identificação de blocos corrompidos em um datafile.
ORA-19566: exceeded limit of 0 corrupt blocks for file /oradata01/oracle/orcl/indices/TBS_INDICES40.dbf
Abrindo o alertlog do banco de dados temos um detalhamento do ocorrido, onde aponta inclusive qual objeto utiliza este bloco.
Mon Oct 03 10:35:02 BRT 2016 Hex dump of (file 439, block 299712) in trace file /home/oracle/home/admin/orcl/udump/orcl_ora_25903.trc Corrupt block relative dba: 0x6dc492c0 (file 439, block 299712) Fractured block found during buffer read Data in bad block: type: 6 format: 2 rdba: 0x6dc492c0 last change scn: 0x0040.47e5f156 seq: 0x1 flg: 0x04 spare1: 0x0 spare2: 0x0 spare3: 0x0 consistency value in tail: 0x00c351d5 check value in block header: 0xd7cb computed block checksum: 0x9ae3 Reread of rdba: 0x6dc492c0 (file 439, block 299712) found same corrupted data Mon Oct 03 10:35:02 BRT 2016 Corrupt Block Found TSN = 25, TSNAME = TBS_INDICES RFN = 439, BLK = 299712, RDBA = 1841599168 OBJN = 60476, OBJD = 60476, OBJECT = IDX_TEST_FK_I, SUBOBJECT = SEGMENT OWNER = PRD, SEGMENT TYPE = Index SegmentApós realizar o rebuild do indice, executei um DBV (DBVERIFY) sobre o arquivo de dados e além do bloco 299712, foram identificados mais 2 blocos corrompidos (299713 e 299714)
Para asber mais sobre o DBV, clique aqui.
Banco=orcl-> dbv file=/oradata01/oracle/orcl/indices/TBS_INDICES40.dbf DBVERIFY: Release 10.2.0.5.0 - Production on Tue Oct 4 08:29:29 2016 Copyright (c) 1982, 2007, Oracle. All rights reserved. DBVERIFY - Verification starting : FILE = /oradata01/oracle/orcl/indices/TBS_INDICES40.dbf Page 299712 is influx - most likely media corrupt Corrupt block relative dba: 0x6dc492c0 (file 439, block 299712) Fractured block found during dbv: Data in bad block: type: 6 format: 2 rdba: 0x6dc492c0 last change scn: 0x0040.47e5f156 seq: 0x1 flg: 0x04 spare1: 0x0 spare2: 0x0 spare3: 0x0 consistency value in tail: 0x00c351d5 check value in block header: 0xd7cb computed block checksum: 0x9ae3 Page 299713 is marked corrupt Corrupt block relative dba: 0x6dc492c1 (file 439, block 299713) Bad header found during dbv: Data in bad block: type: 231 format: 2 rdba: 0x001bfcf8 last change scn: 0x006c.3710b7ec seq: 0xb5 flg: 0x1c spare1: 0x19 spare2: 0x0 spare3: 0x65 consistency value in tail: 0x3f8303ce check value in block header: 0x3903 computed block checksum: 0x0 Page 299714 is marked corrupt Corrupt block relative dba: 0x6dc492c2 (file 439, block 299714) Bad header found during dbv: Data in bad block: type: 231 format: 2 rdba: 0x001bfd08 last change scn: 0x0048.3710b7ec seq: 0x6d flg: 0x6c spare1: 0x19 spare2: 0x0 spare3: 0x5301 consistency value in tail: 0x94410601 check value in block header: 0x1389 computed block checksum: 0x4162 DBVERIFY - Verification complete Total Pages Examined : 408832 Total Pages Processed (Data) : 0 Total Pages Failing (Data) : 0 Total Pages Processed (Index): 405595 Total Pages Failing (Index): 0 Total Pages Processed (Other): 668 Total Pages Processed (Seg) : 0 Total Pages Failing (Seg) : 0 Total Pages Empty : 2566 Total Pages Marked Corrupt : 3 Total Pages Influx : 1 Highest block SCN : 1749727541 (64.1749727541)Voltei na base de dados e verifiquei se havia mais algum segmento utilizando estes blocos:
SQL> SELECT tablespace_name, segment_type, owner, segment_name FROM dba_extents WHERE file_id = 439 and 299712 between block_id AND block_id + blocks - 1 ; no rows selected SQL> SELECT tablespace_name, segment_type, owner, segment_name FROM dba_extents WHERE file_id = 439 and 299713 between block_id AND block_id + blocks - 1 ; no rows selected SQL> SELECT tablespace_name, segment_type, owner, segment_name FROM dba_extents WHERE file_id = 439 and 299714 between block_id AND block_id + blocks - 1 ; no rows selected
Nenhum segmento identificado nestes blocos!
Pois bem, já que não temos nenhum segmento, precisamos formatar este blocos.
Primeiramente identificamos a qual tablespace pertence o arquivo de dados:
SQL> select tablespace_name from dba_data_files where file_name='/oradata01/oracle/orcl/indices/TBS_INDICES40.dbf'; TABLESPACE_NAME ------------------------------ TBS_INDICES
Agora criamos uma tabela abaixo desta tablespace, como no exemplo a seguir:
create table prd.fix_corrupt ( n number, c varchar2(4000) ) PCTFREE 95 tablespace TBS_INDICES;
Utilizei PCTFREE 95 para que posteriormente seja necessário a inserção de menos registros até chegarmos ao bloco corrompido.
Criado a tabela, vamos criar uma trigger para abortar o processo se inserção quando o bloco corrompido for utilizado e nos informar em tela.
CREATE OR REPLACE TRIGGER corrupt_trigger AFTER INSERT ON prd.fix_corrupt REFERENCING OLD AS p_old NEW AS new_p FOR EACH ROW DECLARE corrupt EXCEPTION; BEGIN IF (dbms_rowid.rowid_block_number(:new_p.rowid)=299712) and (dbms_rowid.rowid_relative_fno(:new_p.rowid)=439) THEN RAISE corrupt; END IF; EXCEPTION WHEN corrupt THEN RAISE_APPLICATION_ERROR(-20000, 'Corrupt block has been formatted'); END; /
Na trigger informei rowid_relative_fno(:new_p.rowid)=439 que é meu file_id e o dbms_rowid.rowid_block_number(:new_p.rowid)=299712 que é meu bloco corrompido.
O próximo passo é identificar o tamanho do extent corrompido para que possamos alocá-lo, desta forma realizamos a seguinte consulta na dba_free_space
informando o file_id e o numero do bloco, no meu caso 299712.
SQL> Select BYTES from dba_free_space where file_id=439 and 299712 between block_id and block_id + blocks -1; BYTES ---------- 67108864
Neste caso é 64K (67108864/1024/1024), assim é possivel alocar o extent da seguinte forma:
alter table prd.fix_corrupt allocate extent (DATAFILE '/oradata01/oracle/orcl/indices/TBS_INDICES40.dbf' SIZE 64K);
Como não sabemos se existem muitos extents de 64K livres no datafile, podemos utilizar o seguinte loop para alocar os extents:
**Detalhe**
Antes de executar o comando verificar o maxsize do datafile, ou seja, qual o tamanho maximo que o datafile pode atingir, pois se todos os extents lives
tiverem o mesmo tamanho ele pode crescer o datafile até chegar a este limite.
SQL> select bytes/1024/1024, maxbytes/1024/1024 from dba_data_files where file_name='/oradata01/oracle/orcl/indices/TBS_INDICES40.dbf'; BYTES/1024/1024 MAXBYTES/1024/1024 --------------- ------------------ 3194 3500
Meu datafile neste momento tem 3.194 MB e pode chegar até 3.500 MB
Executando o loop para alocar os extents:
SQL> BEGIN for i in 1..1000000 loop EXECUTE IMMEDIATE 'alter table prd.fix_corrupt allocate extent (DATAFILE '||'''/oradata01/oracle/orcl/indices/TBS_INDICES40.dbf''' ||'SIZE 64K) '; end loop; end ; / 2 3 4 5 6 BEGIN * ERROR at line 1: ORA-01653: unable to extend table PRD.FIX_CORRUPT by 128 in tablespace TBS_INDICES ORA-06512: at line 3
Como podemos ver acima ele alocou extents até estourar o datafile, vamos ver agora o tamanho.
SQL> select bytes/1024/1024, maxbytes/1024/1024 from dba_data_files where file_name='/oradata01/oracle/orcl/indices/TBS_INDICES40.dbf'; BYTES/1024/1024 MAXBYTES/1024/1024 --------------- ------------------ 3500 3500
Como ele estava com maxsize de 3500MB o datafile parou de crescer quando chegou a este valor, se ele fosse de 30G, por exemplo, possivelmente ele iria alocar
toda esta área o que não seria necessário.. sempre observar este fator antes de executar o loop! se for necessário reduzir o maxsize e após as alocações
voltar o valor antigo.
Agora vamos verificar se os blocos estão sendo utilizados pela tabela criada:
SQL> set lines 200 SQL> col segment_name for a70 SQL> select segment_name, segment_type, owner from dba_extents where file_id = 439 and 299712 between block_id and block_id + blocks -1; SEGMENT_NAME SEGMENT_TYPE OWNER ---------------------------------------------------------------------- ------------------ ------------------------------ FIX_CORRUPT TABLE PRD SEGMENT_NAME SEGMENT_TYPE OWNER ---------------------------------------------------------------------- ------------------ ------------------------------ FIX_CORRUPT TABLE PRD SQL> select segment_name, segment_type, owner from dba_extents where file_id = 439 and 299714 between block_id and block_id + blocks -1; SEGMENT_NAME SEGMENT_TYPE OWNER ---------------------------------------------------------------------- ------------------ ------------------------------ FIX_CORRUPT TABLE PRD
Visto que os blocos listados como corrompidos estão sendo alocados pela tabela criada, vamos inserir registros até que o bloco seja preenchido e formatado.
Para isto iremos utilizar um loop de inserção até que a mensagem gerada pela trigger seja exibida na tela:
Begin FOR i IN 1..1000000000 loop for j IN 1..1000 loop Insert into prd.fix_corrupt VALUES(i,'x'); end loop; commit; END LOOP; END; / Begin * ERROR at line 1: ORA-20000: Corrupt block has been formatted ORA-06512: at "SYS.CORRUPT_TRIGGER", line 10 ORA-04088: error during execution of trigger 'SYS.CORRUPT_TRIGGER' ORA-06512: at line 4
Agora executamos um novo DBV para verificar se todos os blocos foram formatados:
Banco=orcl-> dbv file=/oradata01/oracle/orcl/indices/TBS_INDICES40.dbf DBVERIFY: Release 10.2.0.5.0 - Production on Tue Oct 4 09:31:26 2016 Copyright (c) 1982, 2007, Oracle. All rights reserved. DBVERIFY - Verification starting : FILE = /oradata01/oracle/orcl/indices/TBS_INDICES40.dbf DBVERIFY - Verification complete Total Pages Examined : 448000 Total Pages Processed (Data) : 80471 Total Pages Failing (Data) : 0 Total Pages Processed (Index): 358990 Total Pages Failing (Index): 0 Total Pages Processed (Other): 1068 Total Pages Processed (Seg) : 0 Total Pages Failing (Seg) : 0 Total Pages Empty : 7471 Total Pages Marked Corrupt : 0 Total Pages Influx : 0 Highest block SCN : 1758325239 (64.1758325239) Banco=orcl->
Estando o valor de "Total Pages Marked Corrupt" = 0 ficou tudo OK, caso ele ainda indique a presença de blocos corrompidos e sem segmentos basta recriar a
trigger informando o novo bloco, reexecutar o insert e ao final o DBV até que o valor de blocos marcados como corrompidos seja 0.
Ao termino do processo remover a tabela criada:
SQL> drop table prd.fix_corrupt; Table dropped.
Referência:
https://docs.oracle.com/cd/B28359_01/backup.111/b28270/rcmvalid.htm
0 comentários:
Postar um comentário