ORA-01578: ORACLE data block corrupted (file # 377, block #
4205)
ORA-01110: data file 392: '/u01/app/oracle/db/apps_st/data/a_tx_data01.dbf'
ORA-26040: Data block was loaded using the NOLOGGING option
ORA-01110: data file 392: '/u01/app/oracle/db/apps_st/data/a_tx_data01.dbf'
ORA-26040: Data block was loaded using the NOLOGGING option
For Refer :
&AFN is : 392 (from the ORA-1110 portion of the error)
&RFN is : 377 (from the "file #" in the ORA-1578)
&BL is : 4205 (from the "block #" in the ORA-1578)
&FILENAME is : '/d01/app/oracle/db/apps_st/data/a_tx_data01.dbf'
Step 1 .The corrupted blocks are listed in the view
v$database_block_corruption:
SQL> select * from v$database_block_corruption;
Step 2: The
corrupted blocks are listed with Tablsspace
SQL> select b.tablespace_name, count(BLOCK#) from
v$database_block_corruption a, dba_data_files b where a.FILE#=b.FILE_ID group
by b.tablespace_name
Step 3: Identify the corrupt segments It will map each
block from v$database_block_corruption to either a segment or if the block is
free.
SQL> set pagesize 2000
set linesize
250
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#;
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 EMP 6 10 10 1
SCOTT TABLE PARTITION ORDER ORDER_JAN 6 26 28 3
6 29 29 1 Free Block
Step 4:To find the Corrupt Tablespace Name and details ..
SQL> select
b.tablespace_name,count(BLOCK#) from v$database_block_corruption a,
dba_data_files b where a.FILE#=b.FILE_ID group by b.tablespace_name;
An output example is:
TABLESPACE_NAME FILE# BLOCK#
BLOCKS CORRUPTIO
------------------------------ ---------- ----------
---------- ---------
APPS_TS_TX_DATA 06 57997 3 CORRUPT
APPS_TS_TX_DATA 31 16067 1 CORRUPT
APPS_TS_TX_DATA 34 173076 4 CORRUPT
APPS_TS_TX_DATA 392 620
13 CORRUPT
APPS_TS_NOLOGGING 401 2090 5 CORRUPT
Step 5: For each file# need to fire below query and find
the objects that are corrupt & make a note of them. (Replace 06
with file number)
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#
and c.file#=06
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
and c.file#=06
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#
and c.file#=06
order by file#,
corr_start_block#;
Solution :
Import the identified tables & rebuilt the indexes:
Import the identified tables & rebuilt the indexes:
Drop the Tablespace ,Import
from Source to Target:
Source :
expdp system/manager@PRD tablespaces=APPS_TS_TX_DATA directory=txdata dumpfile=appstxdt.dmp logfile=appstxdt.log
expdp system/manager@PRD tablespaces=APPS_TS_TX_DATA directory=txdata dumpfile=appstxdt.dmp logfile=appstxdt.log
Target :
impdp system/manager@DEV tablespaces=APPS_TS_TX_DATA directory=txdata dumpfile=appstxdt.dmp logfile=appstxdt.log
impdp system/manager@DEV tablespaces=APPS_TS_TX_DATA directory=txdata dumpfile=appstxdt.dmp logfile=appstxdt.log
Step 6: Retest the issue
To find the details …. Please check bellow :
1) An absolute FILE NUMBER (&AFN) of the file
containing the corrupt block
SQL> SELECT name FROM v$datafile WHERE file#=&AFN;
Note : The file name of the file containing the corrupt
block (Ex : file # 377)
The
BLOCK NUMBER of the corrupt block in that file (Ex : block # 4205)
2). The tablespace number and name containing the affected
block.
SQL> SELECT ts#
"TSN" FROM v$datafile WHERE file#=&AFN;
SQL> SELECT tablespace_name FROM dba_data_files WHERE
file_id=&AFN;
3). The block size of the tablespace where the corruption
lies
SQL> SELECT block_size FROM dba_tablespaces
WHERE
tablespace_name =
(SELECT tablespace_name FROM
dba_data_files WHERE file_id=&AFN);
4).Identify the Corrupt Object
The database must be open in order to use this query:
The following query will tell you the object TYPE , OWNER and NAME of a segment
SQL> SELECT tablespace_name, segment_type, owner, segment_name
FROM dba_extents WHERE file_id = &AFN
and &BL between block_id AND block_id + blocks – 1;
SQL> select * from dba_extents where file_id = &AFN
and &BL between block_id AND block_id + blocks - 1;
Note : If the block is in a TEMPFILE the above query will return no data
5). If the above query does not return rows, it can also be that the corrupted block is a segment header
in a Locally Managed Tablespace (LMT). When the corrupted block is a segment
header block in a LMT, the above query produces a corruption message in the alert.log
but the query does not not fail. In that case use this query:
SQL> SELECT owner, segment_name, segment_type, partition_name
FROM dba_segments WHERE header_file = &AFN and header_block = &BL;
Reference Note 819533.1(case 5)
6). If the block belongs to a free extent it should appear in DBA_FREE_SPACE:
SQL> select * from dba_free_space
where file_id = &AFN and &BL between block_id AND block_id + blocks - 1;
7). If the segment is a CLUSTER determine which tables it contains.
SQL> SELECT owner, table_name FROM dba_tables
WHERE owner='&OWNER' AND cluster_name='&SEGMENT_NAME';
8). If the segment is an INDEX PARTITION
SQL> SELECT partition_name FROM dba_extents WHERE file_id = &AFN
AND &BL BETWEEN block_id AND block_id + blocks – 1;
Note : then continue below as if the segment was an INDEX segment.
Options:Index partitions can be rebuilt using:
EX: ALTER INDEX xxx REBUILD PARTITION ppp;
INDEX :
- If the segment is an INDEX then if the OWNER is "SYS" contact
Oracle support with all details.
Note: For a non-dictionary INDEX or INDEX PARTITIONs find out which table
the INDEX is on:
Eg:SQL>SELECT table_owner, table_name FROM dba_indexes
WHERE owner='&OWNER' AND index_name='&SEGMENT_NAME';
Note: and determine if the index supports a CONSTRAINT:
Eg:SQL>SELECT owner, constraint_name, constraint_type, table_name
FROM dba_constraints WHERE owner='&TABLE_OWNER'
AND constraint_name='&INDEX_NAME';
Note: Possible values for CONSTRAINT_TYPE are:
P The index supports a primary key constraint.
U The index supports a unique constraint.
Note : If the INDEX supports a PRIMARY KEY constraint (type "P") then
check if the primary key is referenced by any foreign key constraints:
Eg:
SQL> SELECT owner, constraint_name, constraint_type, table_name
FROM dba_constraints WHERE r_owner='&TABLE_OWNER'
AND r_constraint_name='&INDEX_NAME';
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ID 28814.,472231.1,336133.1,819533.1 & 369076.1
+++++++++++++++++++++++++++++++++++++++++++++++++++++
Step 1:
SQL> select * from v$database_block_corruption;SQL> select * from v$datafile where file#='&file#no';SQL> select distinct file# from v$database_block_corruption;SQL> select distinct file#,CORRUPTION_TYPE from V_$DATABASE_BLOCK_CORRUPTION order by file#;SQL> select file_id,file_name from dba_data_files where file_id in (no1,n02,no3,no4);SQL> select owner, segment_name,tablespace_name from dba_extents where FILE_ID=&id and <Block> between BLOCK_ID and BLOCK_ID+BLOCKS;Step 2: Check whether block is part of any objectQuery dba_extents and cross check the block doesnot belong to any object.SQL> select segment_name,segment_type, owner from dba_extentswhere file_id = <Absolute filenumber> and <corrupted block number>between block_id and block_id + blocks -1;Note : If it doesn't belong to an object, double check if itdoes exists in dba_free_space to check if the block belongs to file space usage bitmap.SQL> Select * from dba_free_space where file_id= <Absolute file number>and <corrupted block number> between block_id and block_id + blocks -1;Step 3: We cannot run a query on dba_extents to find out what the object is on the standby, so we ran the following query on the Primary to find the corrupted block:SQL> SELECT tablespace_name, segment_type, owner, segment_nameFROM dba_extents WHERE file_id = &no-start and &no-end between block_id AND block_id + blocks - 1;Step 4: The repair data block of table in a given tablespace:SQL> BEGINDBMS_REPAIR.ADMIN_TABLES (TABLE_NAME => 'REPAIR_TABLE',TABLE_TYPE => dbms_repair.repair_table,ACTION => dbms_repair.create_action,TABLESPACE => '&tablespace_name');END;/Step 5: Identify corrupted blocks for schema.object:SQL> set serveroutput onSQL> DECLARE num_corrupt INT;BEGINnum_corrupt := 0;DBMS_REPAIR.CHECK_OBJECT (SCHEMA_NAME => '&schema_name',OBJECT_NAME => '&object_name',REPAIR_TABLE_NAME => 'REPAIR_TABLE',corrupt_count => num_corrupt);DBMS_OUTPUT.PUT_LINE('number corrupt: ' || TO_CHAR (num_corrupt));END;Step 6: Optionally display any corrupted block identified by check_object:SQL> select BLOCK_ID,CORRUPT_TYPE, CORRUPT_DESCRIPTION from REPAIR_TABLE;Step 7: Mark the identified blocks as corruptedSQL> DECLARE num_fix INT;BEGINnum_fix := 0;DBMS_REPAIR.FIX_CORRUPT_BLOCKS (SCHEMA_NAME => '&schema_name',OBJECT_NAME=> '&object_name',OBJECT_TYPE => dbms_repair.table_object,REPAIR_TABLE_NAME => 'REPAIR_TABLE',FIX_COUNT=> num_fix);DBMS_OUTPUT.PUT_LINE('num fix: ' || to_char(num_fix));END;/Step 8 : To find the corruption objectsSQL> select count(*) from v$database_block_corruption;SQL> select 'SELECT e.file_id,e.block_id,e.owner,e.segment_name,e.segment_type FROM dba_extents e WHEREfile_id='|| file#||' and '|| block#||' BETWEEN block_id AND block_id + blocks - 1; 'from v$database_block_corruption order by file#;Note :Allow future DML statements to skip the corrupted blocksNote : If it is needed to stop skipping corrupt blocks in the object -- ID 556733.1:SQL> BEGINDBMS_REPAIR.SKIP_CORRUPT_BLOCKS (SCHEMA_NAME => '&schema_name',OBJECT_NAME => '&object_name',OBJECT_TYPE => dbms_repair.table_object,FLAGS => dbms_repair.SKIP_FLAG);END;/Note : if not required :SQL> execute dbms_backup_restore.resetCfileSection(file#); /** clear v$backup_corruptionTo verify :SQL> SELECT OBJECT_NAME, BLOCK_ID, CORRUPT_TYPE, MARKED_CORRUPT,CORRUPT_DESCRIPTION,EPAIR_DESCRIPTION FROM REPAIR_TABLE;SQL> select * from V$DATABASE_BLOCK_CORRUPTION ;RMAN VerifyTo identify both Physical and Logical Block Corruptions use the "CHECK LOGICAL" option. The next command checks the complete database for both corruptions without actually doing a backup:$ rman target /RMAN> backup check logical validate database;Note : The next command checks the complete database for both corruptions in a backup:$ rman target /RMAN> backup check logical databaseDBVerify - Identify Datafile Block CorruptionsDBVERIFY identify Physical and Logical Intra BlockCorruptions by default. Dbverify cannot be run for the whole database in a single command. It does not need a database connection either:dbv file=<datafile name> blocksize=<datafile Block size>SQL> connect internalConnected.SQL> show parameter db_block_sizeSQL>select file#,name,bytes/2048 from v$datafile;SQL> EXIT$dbv file=/u02/oradata/R815/oradata/R815/users01.dbf blocksize=2048 logfile=users01_dbv.log feedback=100++++++++++++++++++++++++++++++++++++++++++++++
No comments:
Post a Comment