Oracle 19c ASM Storage: Block Corruption

 Oracle 19c ASM Storage: Block Corruption

Special errors, step-by-step diagnosis and fix, with live examples

Environment used in all examples: Oracle 19c EE, database PRODDB, ASM instance +ASM1, diskgroups +DATA and +FRA, host dbprod01, OS Oracle Linux with multipath. Sample outputs are illustrative of what each error looks like; replace file numbers, block numbers and disk names with your own values.

Rule for every case: identify the layer first (database, ASM, OS/storage), then fix at that layer. Never repair at the database layer if the storage layer is still failing.

1. Quick triage table

Error

Layer

Meaning / go to

ORA-01578 + ORA-01110

Database

Physical block corruption in a datafile. Case A

ORA-15130 / ORA-15075 / ORA-27072 in ASM log; disk OFFLINE

ASM / storage

Disk dropped or offlined after I/O error. Case B

ORA-15032 + ORA-15040 + ORA-15042

ASM

Diskgroup will not mount, disk missing. Case C

ORA-15196, ORA-15036

ASM

Invalid ASM block or disk header. Case D

ORA-26040

Database

NOLOGGING block, logically corrupt. Case E

ORA-00600 [kcbz_check_objd_typ]

Database

Block/object mismatch, in-memory or lost write. Case F

ORA-15080 / ORA-15081 / ORA-27072

OS / storage

I/O failed or could not be submitted. Case G

2. Common first steps (always run)

Step 1: Read both alert logs

# as oracle (database)

adrci> set home diag/rdbms/proddb/PRODDB

adrci> show alert -tail 200

 

# as grid (ASM)

adrci> set home diag/asm/+asm/+ASM1

adrci> show alert -tail 200

 

grep -E "ORA-01578|ORA-01110|ORA-26040|ORA-00600|ORA-15[0-9]{3}|ORA-27[0-9]{3}" alert_*.log | tail -50

 

Step 2: ASM layer health (as grid, sqlplus / as sysasm)

SELECT name,state,type,total_mb,free_mb,offline_disks FROM v$asm_diskgroup;

 

SELECT group_number gn,disk_number dn,name,path,mode_status,state,header_status,

       read_errs,write_errs FROM v$asm_disk ORDER BY 1,2;

 

SELECT * FROM v$asm_operation;

 

Healthy output: state MOUNTED, offline_disks 0, mode_status ONLINE, header_status MEMBER, read_errs and write_errs 0, no rows in v$asm_operation. Anything else points to Case B, C, D or G.

Step 3: Database layer scope

SELECT file#,block#,blocks,corruption_type FROM v$database_block_corruption;

 

rman target /

RMAN> VALIDATE CHECK LOGICAL DATABASE;

 

Step 4: OS and storage layer

dmesg -T | grep -iE "i/o error|scsi|multipath|blk_update|reset"

tail -200 /var/log/messages

multipath -ll

ls -l /dev/mapper/ /dev/oracleasm/disks/    # owner must be grid:asmadmin, mode 660

 

Case A: ORA-01578 / ORA-01110 physical block corruption

Live example: error as seen

ORA-01578: ORACLE data block corrupted (file # 7, block # 128945)

ORA-01110: data file 7: '+DATA/PRODDB/DATAFILE/users.259.1098123456'

 

Step A1: Confirm and list all corrupt blocks

SQL> SELECT file#,block#,blocks,corruption_type FROM v$database_block_corruption;

 

FILE#  BLOCK#   BLOCKS CORRUPTION_TYPE

----- -------- ------- ---------------

    7   128945       1 CORRUPT

 

Step A2: Find the affected object

SELECT owner,segment_name,segment_type,tablespace_name

FROM dba_extents

WHERE file_id=7 AND 128945 BETWEEN block_id AND block_id+blocks-1;

 

OWNER   SEGMENT_NAME   SEGMENT_TYPE   TABLESPACE_NAME

------- -------------- -------------- ---------------

APPS    XX_GL_LINES    TABLE          USERS

 

No rows returned means the block is free space or the file header; RMAN repair still applies.

Step A3: Rule out storage cause first

Run Step 2 and Step 4 above. If read_errs is non-zero or dmesg shows I/O errors, fix Case B or G first, otherwise the block will be corrupted again.

Step A4: Repair with RMAN block media recovery (best method)

RMAN> RECOVER DATAFILE 7 BLOCK 128945;

 

-- or repair everything listed in v$database_block_corruption:

RMAN> RECOVER CORRUPTION LIST;

 

Starting recover at 16-OCT-26

channel ORA_DISK_1: restoring block(s) from datafile backup set

starting media recovery

media recovery complete, elapsed time: 00:00:04

Finished recover at 16-OCT-26

 

Needs a valid backup of the datafile plus archivelogs (or flashback logs). Database stays open, only that block is unavailable during the repair.

Step A5: Verify

RMAN> VALIDATE DATAFILE 7 CHECK LOGICAL;

SQL> SELECT * FROM v$database_block_corruption;     -- expect no rows

 

Fallback when no backup exists

•      Index block: ALTER INDEX owner.idx REBUILD ONLINE; (data is rebuilt from the table, no loss).

•      Table block: salvage rows with DBMS_REPAIR, then CTAS to a new table. Rows in the bad block are lost.

EXEC DBMS_REPAIR.ADMIN_TABLES('REPAIR_TABLE',DBMS_REPAIR.REPAIR_TABLE,DBMS_REPAIR.CREATE_ACTION,'USERS');

 

DECLARE n BINARY_INTEGER; BEGIN

  DBMS_REPAIR.CHECK_OBJECT('APPS','XX_GL_LINES',corrupt_count=>n);

  DBMS_OUTPUT.PUT_LINE('corrupt='||n);

END; /

 

EXEC DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('APPS','XX_GL_LINES',flags=>DBMS_REPAIR.SKIP_FLAG);

 

CREATE TABLE apps.xx_gl_lines_new AS SELECT * FROM apps.xx_gl_lines;

-- compare counts, rename, recreate indexes, constraints, grants, then drop the old table

 

Case B: ASM disk offlined after I/O error

Live example: error as seen (ASM alert log)

WARNING: Write Failed. group:1 disk:3 AU:5120 offset:0 size:4096

ORA-27072: File I/O error

Linux-x86_64 Error: 5: Input/output error

NOTE: process _user12345_+asm1 initiating offline of disk 3.3915941234 (DATA_0003) with mask 0x7e in group 1

WARNING: Disk 3 (DATA_0003) in group 1 will be dropped in: (12960) secs on ASM inst 1

 

The 12960 seconds is disk_repair_time (3.6 hours). If the disk comes back before the timer ends, ASM only resyncs changed extents. After it expires the disk is force-dropped and a full rebalance is needed.

Step B1: Check state and redundancy

SELECT name,type,offline_disks FROM v$asm_diskgroup;

SELECT name,path,mode_status,mount_status,header_status,repair_timer FROM v$asm_disk WHERE group_number=1;

 

NAME        MODE_STATUS  MOUNT_STATUS  HEADER_STATUS  REPAIR_TIMER

----------- ------------ ------------- -------------- ------------

DATA_0003   OFFLINE      MISSING       UNKNOWN        11840

 

•      EXTERNAL redundancy: the diskgroup is dismounted or at risk. Treat as an outage and go to Case C and the restore path.

•      NORMAL or HIGH redundancy: ASM serves reads from the mirror and also auto-repairs corrupt blocks from the good copy. The database keeps running.

Step B2: Fix the OS path (before touching ASM)

multipath -ll | grep -A6 DATA_0003

multipathd -k"show paths"

multipath -r                     # reload maps after storage team fixes the LUN/HBA

ls -l /dev/mapper/DATA_0003      # must be grid:asmadmin 660

 

Step B3: Bring the disk online

SQL> ALTER DISKGROUP DATA ONLINE DISK DATA_0003;

-- or all offline disks:

SQL> ALTER DISKGROUP DATA ONLINE ALL;

 

SQL> SELECT group_number,operation,state,power,est_minutes FROM v$asm_operation;

GROUP_NUMBER OPERATION STATE POWER EST_MINUTES

------------ --------- ----- ----- -----------

           1 REBAL     RUN       4           6

 

Step B4: If the disk was already force-dropped

-- repair timer expired; disk header_status is now FORMER or CANDIDATE

SQL> ALTER DISKGROUP DATA ADD DISK '/dev/mapper/DATA_0003' NAME DATA_0003 REBALANCE POWER 4;

 

Step B5: Verify

SQL> SELECT name,state,offline_disks FROM v$asm_diskgroup;      -- offline_disks 0

SQL> SELECT * FROM v$asm_operation;                              -- no rows when done

$ asmcmd lsdg

 

Do not drop other disks while a rebalance is running.

Case C: Diskgroup will not mount (ORA-15032 / ORA-15040 / ORA-15042)

Live example: error as seen

SQL> ALTER DISKGROUP DATA MOUNT;

ERROR at line 1:

ORA-15032: not all alterations performed

ORA-15040: diskgroup is incomplete

ORA-15042: ASM disk "3" is missing from group number "1"

 

Step C1: Which disks does ASM actually see

$ kfod disks=all status=true op=disks

$ asmcmd lsdsk --candidate -p

SQL> SHOW PARAMETER asm_diskstring

 

Compare against the expected disk count of the diskgroup. A disk missing here means OS, multipath, permission or asm_diskstring problem, not an ASM problem.

Step C2: Fix the visibility problem

•      Permissions or ownership reset after reboot/patch: chown grid:asmadmin and chmod 660, fix udev rules or AFD labels.

•      asm_diskstring does not match the device path: correct it and re-run kfod.

•      Multipath path down: see Case B Step B2.

Step C3: Mount

SQL> ALTER DISKGROUP DATA MOUNT;

 

Step C4: If a disk is truly lost and redundancy is NORMAL or HIGH

SQL> ALTER DISKGROUP DATA MOUNT FORCE;

-- then repair or replace the lost disk as in Case B Step B4

 

MOUNT FORCE does not help with EXTERNAL redundancy. In that case, the only path is restore from RMAN backup to a healthy diskgroup, or amdu to extract files from the surviving disks.

Step C5: Verify

$ asmcmd lsdg

SQL> ALTER DISKGROUP DATA CHECK ALL NOREPAIR;   -- then read the ASM alert log result

srvctl start database -d PRODDB

 

Case D: ASM disk header corruption (ORA-15196 / ORA-15036)

Live example: error as seen

ORA-15196: invalid ASM block header [kfc.c:26076] [endian_kfbh] [2147483648] [0] [0 != 1]

ORA-15040: diskgroup is incomplete

WARNING: cache read a corrupt block: group=1(DATA) dsk=3 blk=1 disk=3 (DATA_0003) incarn=...

 

Step D1: Take a metadata and header backup first

$ asmcmd md_backup /tmp/dg_data.mdb -G DATA          # only if the diskgroup is mountable

$ dd if=/dev/mapper/DATA_0003 of=/tmp/DATA_0003.hdr bs=4096 count=1

 

Step D2: Read the primary header

$ kfed read /dev/mapper/DATA_0003 | egrep "kfbh.type|kfdhdb.hdrsts|kfdhdb.dskname|kfdhdb.grpname"

 

kfbh.type:    0 ; 0x002: KFBTYP_INVALID       <-- corrupt (healthy is KFBTYP_DISKHEAD)

kfdhdb.hdrsts: 0

 

Step D3: Confirm the backup header is intact

$ kfed read /dev/mapper/DATA_0003 aun=1 blkn=254 | egrep "kfbh.type|kfdhdb.hdrsts|kfdhdb.dskname"

 

kfbh.type:    1 ; 0x002: KFBTYP_DISKHEAD     <-- good

kfdhdb.hdrsts: 3 ; 0x027: KFDHDR_MEMBER

kfdhdb.dskname: DATA_0003

 

Step D4: Repair the header

$ kfed repair /dev/mapper/DATA_0003

$ kfed read /dev/mapper/DATA_0003 | grep kfbh.type      # expect KFBTYP_DISKHEAD

 

Step D5: Mount and verify

SQL> ALTER DISKGROUP DATA MOUNT;

SQL> ALTER DISKGROUP DATA CHECK ALL NOREPAIR;

SQL> SELECT name,header_status,mode_status FROM v$asm_disk WHERE group_number=1;

 

If the backup header is also bad, stop. Use amdu to extract datafiles from the diskgroup, or restore from backup, and raise an Oracle Support SR.

Case E: ORA-26040 data block loaded with NOLOGGING

Live example: error as seen

ORA-01578: ORACLE data block corrupted (file # 9, block # 40210)

ORA-01110: data file 9: '+DATA/PRODDB/DATAFILE/xxgl_data.301.1098333111'

ORA-26040: Data block was loaded using the NOLOGGING option

 

Cause: a direct-path load or NOLOGGING operation (CTAS, INSERT /*+ APPEND */, index create) wrote blocks with no redo. After a restore/recovery or on a standby, those blocks are marked logically corrupt. This is not a hardware problem.

Step E1: Identify object and confirm NOLOGGING origin

SELECT owner,segment_name,segment_type FROM dba_extents

WHERE file_id=9 AND 40210 BETWEEN block_id AND block_id+blocks-1;

 

SELECT file#,unrecoverable_change#,unrecoverable_time FROM v$datafile WHERE file#=9;

SELECT force_logging FROM v$database;

 

Step E2: Fix

Redo does not exist for those blocks, so RMAN cannot repair them. Re-create the data from its source:

•      Index: ALTER INDEX owner.idx REBUILD;

•      Table: truncate and reload, or re-run the original load job, or recreate from source/export.

Step E3: Prevent

SQL> ALTER DATABASE FORCE LOGGING;

SQL> SELECT force_logging FROM v$database;     -- YES

RMAN> BACKUP DATABASE PLUS ARCHIVELOG;       -- after any unavoidable NOLOGGING operation

 

Case F: ORA-00600 [kcbz_check_objd_typ]

Live example: error as seen

ORA-00600: internal error code, arguments: [kcbz_check_objd_typ_2], [0], [0], [1], [], [], [], [], [], [], [], []

Incident 12345 created, trace: .../diag/rdbms/proddb/PRODDB/trace/PRODDB_ora_28811.trc

 

Meaning: the block read does not match the object that owns it. Causes: in-memory corruption, lost write by storage, or a real on-disk corruption. Treat it as corruption until proven otherwise.

Step F1: Get the incident details

adrci> show incident

adrci> show incident -mode detail -p "incident_id=12345"

adrci> ips pack incident 12345            # package for Oracle Support

 

Step F2: Find the file and block in the trace

grep -iE "file#|rdba|dba:|obj#|dataobj" PRODDB_ora_28811.trc | head -20

 

-- convert rdba to file/block

SELECT dbms_utility.data_block_address_file(TO_NUMBER('01c1f2d1','xxxxxxxx')) fno,

       dbms_utility.data_block_address_block(TO_NUMBER('01c1f2d1','xxxxxxxx')) bno FROM dual;

 

Step F3: Validate the object and the file

RMAN> VALIDATE DATAFILE <fno> CHECK LOGICAL;

SQL> ANALYZE TABLE apps.xx_gl_lines VALIDATE STRUCTURE CASCADE ONLINE;

$ dbv file=<datafile> blocksize=8192       # for non-ASM copies; for ASM use RMAN VALIDATE

 

Step F4: Fix by outcome

•      RMAN reports the block in v$database_block_corruption: use Case A Step A4.

•      Clean validate but error repeats: bounce the instance to clear the buffer cache, check bug notes in My Oracle Support for the exact first argument and your RU level, and open an SR with the ips package.

•      Repeats across blocks/files: suspect storage lost writes. Engage the storage team and enable the checks below.

ALTER SYSTEM SET db_block_checksum=FULL SCOPE=BOTH;

ALTER SYSTEM SET db_block_checking=MEDIUM SCOPE=BOTH;

ALTER SYSTEM SET db_lost_write_protect=TYPICAL SCOPE=BOTH;

 

Note: db_block_checking adds CPU overhead; test impact before leaving it on in production.

Case G: ORA-15080 / ORA-15081 / ORA-27072 I/O errors

Live example: error as seen

ORA-15080: synchronous I/O operation failed to read block 0 of disk 3 in disk group DATA

ORA-15081: failed to submit an I/O operation to a disk

ORA-27072: File I/O error

Additional information: 4

 

Step G1: Prove it is the OS or storage

dmesg -T | grep -iE "i/o error|sd[a-z]+|blk_update_request|Medium Error"

journalctl -k --since "2 hours ago" | grep -i error

multipath -ll

dd if=/dev/mapper/DATA_0003 of=/dev/null bs=1M count=100 iflag=direct    # read test as grid

 

Step G2: Fix

•      Dead path or flapping HBA: storage/SAN team fixes zoning, cable, HBA; then multipath -r.

•      Permission change after reboot or patch: restore grid:asmadmin 660 on the device.

•      Failing LUN or disk: have storage replace it, then follow Case B Step B4 to add it and rebalance.

Step G3: Bring ASM and DB back to a clean state

SQL> ALTER DISKGROUP DATA ONLINE ALL;

SQL> SELECT * FROM v$asm_operation;

RMAN> VALIDATE CHECK LOGICAL DATABASE;

SQL> SELECT * FROM v$database_block_corruption;     -- expect no rows

 

Final validation and prevention checklist

•      asmcmd lsdg: all diskgroups MOUNTED, offline_disks 0, adequate free space for rebalance.

•      v$asm_disk: read_errs and write_errs 0, header_status MEMBER.

•      v$database_block_corruption: no rows. RMAN VALIDATE CHECK LOGICAL DATABASE clean.

•      Take a fresh level 0 backup and run RMAN CROSSCHECK; confirm archivelogs are continuous.

•      Set db_block_checksum=TYPICAL or FULL, db_block_checking=MEDIUM (after load test), FORCE LOGGING on.

•      Schedule regular asmcmd md_backup and a weekly RMAN VALIDATE CHECK LOGICAL.

•      Use Data Guard (Active Data Guard auto block repair) where possible.

•      Raise the root cause (SAN, HBA, multipath, firmware) with the storage team and record the RCA.

Do not do

•      Do not run kfed repair or ALTER DISKGROUP ... REPAIR before taking a backup and a metadata dump.

•      Do not set _allow_resetlogs_corruption or _corrupted_rollback_segments without Oracle Support.

•      Do not drop disks while a rebalance is running.

•      Do not run DBMS_REPAIR skip and CTAS on a table and discard the original before comparing row counts.

Comments

Popular posts from this blog

Cloning Oracle E-Business Suite 12.2.11: RMAN + Rapid Clone

Configure Oracle Database Vault Realms

Data Guard & RMAN Configuration