Wednesday, September 30, 2015

Important

Corruption at empty blocks

https://support.oracle.com/epmos/faces/DocumentDisplay?_afrLoop=354717203845222&parent=DOCUMENT&sourceId=794505.1&id=336133.1&_afrWindowMode=0&_adf.ctrl-

state=oraf5szyy_191

Table

https://support.oracle.com/epmos/faces/DocumentDisplay?_afrLoop=354721681748824&parent=DOCUMENT&sourceId=794505.1&id=556733.1&_afrWindowMode=0&_adf.ctrl-

state=oraf5szyy_240

LOB

https://support.oracle.com/epmos/faces/DocumentDisplay?_afrLoop=354724139149126&parent=DOCUMENT&sourceId=794505.1&id=293515.1&_afrWindowMode=0&_adf.ctrl-

state=oraf5szyy_281

Validate database through RMAN


We can use backup validate command to check the database for any physical / logical block corruptions.

Step 1:

1) Connect to RMAN

2) backup validate check logical database;

3) We can omit backup keyword from Oracle 11g onward and the above command will not take the backup of the database. It only check for any logical / physical corruptions in the database.

4) To complete the command faster configure number of channels its depends on number of CPUs as well as database edition.

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

OR

RMAN> run {
allocate channel d1 type disk;
allocate channel d2 type disk;
allocate channel d3 type disk;
allocate channel d4 type disk;
backup validate check logical database;
}

5) If any of the datafiles are missing then use clause SKIP INACCESSIBLE in the above command to get succeed.

6) The CHECK LOGICAL option checks for both PHYSICAL and LOGICAL Block corruptions.

7) For a single or specific datafiles use

              check logical validate datafile 1;

8) Monitoring Validate command progress

select sid, serial#, context, sofar, totalwork,round(sofar/totalwork*100,2) "%_complete"
from v$session_longops
where opname like 'RMAN%'
  and opname not like '%aggregate%'
  and totalwork != 0
  and sofar <> totalwork;

9) In 11g RMAN generates a trace file with the details of the corruption description

10) From 11g, the validation of a single datafile can be made parallel by using the section clause. RMAN divides the file into sections and processes each file section in parallel. The following example divides the datafile 5 into 1 gb sections when multiple channels are configured or allocated and each section is run in parallel

backup validate check logical datafile 5 SECTION SIZE 1024M;

11) From 11g onward a range of blocks can be checked within a datafile using the BLOCK TO clause. The following command will check blocks from 5 to 20 of datafile 1:

validate check logical datafile 1 BLOCK 5 TO 20;

Step 2: Identify the corrupt segments

$ sqlplus / as sysdba
set pagesize 2000
set linesize 280
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
     , corruption_type 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
     , corruption_type||' 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#;


An output example is:

OWNER SEGMENT_TYPE       SEGMENT_NAME PARTITION_ FILE# CORR_START_BLOCK# CORR_END_BLOCK# BLOCKS_CORRUPTED DESCRIPTION
----- ------------------ ------------ ---------- ----- ----------------- --------------- ---------------- -------------
SCOTT TABLE              EMP                         6                10              10                1
SCOTT TABLE PARTITION    ORDER        ORDER_JAN      6                26              28                3
                                                     6                29              29                1 Free Block
SCOTT TABLE              BONUS                       6                34              34                1
                                                     6                35              35                1 Free Block
SCOTT TABLE              DEPT                        6                42              42                1 Segment Header
SCOTT TABLE              INVOICE                     6                50              50                1

Oracle Block Corruption - ORA-01578 ORA-01110 ORA-26040


The following errors were triggered in the alert log file.

ORA-01578: ORACLE data block corrupted (file # 11, block # 84)
ORA-01110: data file 5: '/oradata/users.dbf'
ORA-26040: Data block was loaded using the NOLOGGING option


Step 1:

If the error is after RMAN duplicate / RESTORE then enable force logging at source database and perform duplicate / restore with new RMAN backup.

Enabling force logging:

alter database force logging;

Step 2:

If the error is produced at physical standby database, Then the option is to restore the datafile from primary only if the primary database's datafile is in good condition. To avoid this problem from being introduced enable force logging at primary.

Note:-We can do exp/imp of the corrupted objects only if the corrupted object(block) is not of type index.

Identify the affected segment:

File numbers can be absolute file number(AFN) and relative file number(RFN), In most of the cases both are identical but can be different when the database has been migrated from 7i or transportable/plugged tablespaces were used.

Getting absolute file number:

The absolute file number is provide by the error line ORA-01110 which can be found after the error ORA-01578 line, From the above errors AFN is 5. We can get AFN using RFN using DBA_DATA_FILES.


We can use the following utilities to check for the corruption in the database.

1) RMAN

2) DBV

3) select * from v$database_block_corruption;


DBV will give information about the corrupted blocks in different ways. In general, It provides relative data block address (RDBA) associated with the effected block.

e.g.

Page 34 is marked corrupt
Corrupt block relative dba: 0x02c00022 (file 11, block 34)
Bad check value found during dbv:
Data in bad block:
 type: 6 format: 2 rdba: 0x02c00022
 last change scn: 0x0771.4eebe71c seq: 0x2 flg: 0x04
 spare1: 0x0 spare2: 0x0 spare3: 0x0
 consistency value in tail: 0xe71c0602
 check value in block header: 0xd3ce
 computed block checksum: 0x2


In the above e.g. 0x02c00022 is the hex decimal block address and 11 is the RFN and 34 is block number.

Another way DBV will report the information about the corrupted blocks as follows.

DBV-200: Block, dba 46137379, already marked corrupted"

Here we use below query to find the RFN and Block number.

select dbms_utility.data_block_address_file(&&rdba) RFN,
dbms_utility.data_block_address_block(&&rdba) BL
from dual;
Enter value for rdba: 46137379

RFN        BL
---------- ----------
11         35

Getting AFN from RFN:

select file_id AFN, relative_fno, tablespace_name
from dba_data_files
where relative_fno=&RFN;
Enter value for rfn: 11

AFN        RELATIVE_FNO TABLESPACE_NAME
---------- ------------ ------------------------------

5          11           USERS


RMAN reports information about the corrupted blocks in v$database_block_corruption.


Step 3:

Identifying the corrupted objects:

select *
from dba_extents
where file_id = &AFN
and &BL between block_id AND block_id + blocks - 1;

It will give list of objects and its types resides in the corrupted blocks.
If the above query does't return any rows then corruption is at segment header in LMTS and if the the corruption is at segment header then the above query produces a corruption message is alertlog file and query will not fail. In that case run the following query

select owner, segment_name, segment_type, partition_name
from   dba_segments
where  header_file = &AFN
  and  header_block = &BL;

If the corrupted block belongs to a free extent i.e block that is not associated to any object or if the corrupted block is in temp file then the above queries returns no data. For TEMP FILES segment type will be temporary, If the block belongs to a free extent it should appear in DBA_FREE_SPACE

select *
from  dba_free_space
where file_id = &AFN
  and &BL between block_id AND block_id + blocks - 1;

//** Identified object can be a free block (or) an index (or) a table (or) a LOB **//

If the identified block is an index type then drop and recreate index to resolve the error.

In our case the object type is index, So we have dropped and recreated indexes which resolved the issue.

Note:- Further document will be updated soon


The identified block is a FREE Block,

If the NOLOGGING Block is a FREE Block, there is the option to wait until the block is reused which will automatically re-format the block or force re-formatting the block using Doc ID 336133.1

The identified block holds a TABLE,

DBMS_REPAIR.SKIP_CORRUPT_BLOCKS can be used to skip the corrupt block in SQL statements;

Doc ID 556733.1 has a DBMS_REPAIR example.

Then decide to re-create the segment: by moving the table: alter table &table_name move;

OR

by saving the data (export, Create Table as Select, etc) and then truncate or drop/create.

The identified block holds LOB,

If it is a LOB use Doc ID 293515.1