Skip to content

ORA-01578: ORACLE Data Block Corrupted (file#, block#)

ORA-01578 indicates that Oracle has detected corruption in a data block. This is a serious error that can result in data loss if not handled properly. The error typically includes the file number and block number of the corrupted block.

ORA-01578: ORACLE data block corrupted (file# [file_number], block# [block_number])
ORA-01110: data file [file_number]: '[file_path]'

🔴 CRITICAL - Indicates data corruption that can lead to data loss and database instability.

  • Disk drive failures or errors
  • Memory corruption
  • Controller problems
  • Cable or connection issues
  • File system corruption
  • I/O subsystem problems
  • Power failures during writes
  • Operating system bugs
  • SAN/NAS configuration problems
  • RAID controller failures
  • Storage array issues
  • Network storage interruptions
  • Oracle bugs (rare)
  • Improper shutdown procedures
  • Concurrent access conflicts
  • Recovery operation errors
-- Check for corruption in a specific file and block
SELECT * FROM v$database_block_corruption
WHERE file# = &file_number AND block# = &block_number;
-- Check all known corruptions
SELECT file#, block#, blocks, corruption_type, corruption_change#
FROM v$database_block_corruption
ORDER BY file#, block#;
-- Get file information
SELECT file#, name, status, bytes/1024/1024 as size_mb
FROM v$datafile
WHERE file# = &file_number;
-- Check database status
SELECT status FROM v$instance;
SELECT open_mode FROM v$database;
-- Check for additional errors in alert log
SELECT message_text, originating_timestamp
FROM v$diag_alert_ext
WHERE message_text LIKE '%ORA-01578%'
OR message_text LIKE '%corrupt%'
OR message_text LIKE '%checksum%'
ORDER BY originating_timestamp DESC;
-- Check datafile status
SELECT file#, status, enabled, name
FROM v$datafile
ORDER BY file#;
-- Find objects affected by the corrupted block
SELECT owner, segment_name, segment_type, tablespace_name
FROM dba_extents
WHERE file_id = &file_number
AND &block_number BETWEEN block_id AND block_id + blocks - 1;
-- Check if it's a table or index
SELECT object_name, object_type, owner
FROM dba_objects o, dba_extents e
WHERE o.owner = e.owner
AND o.object_name = e.segment_name
AND e.file_id = &file_number
AND &block_number BETWEEN e.block_id AND e.block_id + e.blocks - 1;
-- Block media recovery for specific blocks
-- Note: Database must be in ARCHIVELOG mode
-- Check if database is in archivelog mode
SELECT log_mode FROM v$database;
-- Perform block media recovery
RECOVER DATAFILE &file_number BLOCK &block_number;
-- For multiple blocks
RECOVER DATAFILE 4 BLOCK 123, 124, 125;
-- Verify recovery
SELECT * FROM v$database_block_corruption
WHERE file# = &file_number AND block# = &block_number;
Terminal window
# Connect to RMAN
rman target /
# Recover specific corrupted blocks
BLOCKRECOVER DATAFILE 4 BLOCK 123;
# Recover from backups if needed
BLOCKRECOVER DATAFILE 4 BLOCK 123 FROM BACKUPSET;
# Recover multiple blocks
BLOCKRECOVER DATAFILE 4 BLOCK 123, 124, 125;
# Recover all known corrupted blocks
BLOCKRECOVER CORRUPTION LIST;
# Validate after recovery
VALIDATE DATAFILE 4;
-- Option 1: Export/Import uncorrupted data
CREATE TABLE employees_backup AS
SELECT * FROM employees
WHERE ROWID NOT IN (
SELECT ROWID FROM employees
WHERE ROWNUM <= 1 -- This will fail on corrupted blocks
);
-- Option 2: Use DBMS_REPAIR for advanced recovery
-- Create repair table
BEGIN
DBMS_REPAIR.ADMIN_TABLES(
table_name => 'REPAIR_TABLE',
table_type => DBMS_REPAIR.REPAIR_TABLE,
action => DBMS_REPAIR.CREATE_ACTION,
tablespace => 'USERS'
);
END;
/
-- Check for corruption
DECLARE
v_corrupt_count NUMBER;
BEGIN
v_corrupt_count := DBMS_REPAIR.CHECK_OBJECT(
schema_name => 'HR',
object_name => 'EMPLOYEES',
repair_table_name => 'REPAIR_TABLE'
);
DBMS_OUTPUT.PUT_LINE('Corrupted blocks: ' || v_corrupt_count);
END;
/
-- Fix corruption by marking blocks as software corrupt
DECLARE
v_fix_count NUMBER;
BEGIN
v_fix_count := DBMS_REPAIR.FIX_CORRUPT_BLOCKS(
schema_name => 'HR',
object_name => 'EMPLOYEES',
object_type => DBMS_REPAIR.TABLE_OBJECT,
repair_table_name => 'REPAIR_TABLE'
);
DBMS_OUTPUT.PUT_LINE('Fixed blocks: ' || v_fix_count);
END;
/
-- Drop and recreate the index
-- First identify the index
SELECT index_name, owner, table_name
FROM dba_indexes
WHERE index_name IN (
SELECT segment_name
FROM dba_extents
WHERE file_id = &file_number
AND &block_number BETWEEN block_id AND block_id + blocks - 1
);
-- Drop the corrupted index
DROP INDEX hr.emp_dept_idx;
-- Recreate the index
CREATE INDEX hr.emp_dept_idx ON hr.employees(department_id);
-- Or rebuild if possible
ALTER INDEX hr.emp_dept_idx REBUILD;
-- If corruption is extensive, consider tablespace recovery
-- Take tablespace offline
ALTER TABLESPACE users OFFLINE IMMEDIATE;
-- Restore datafile from backup (RMAN)
RESTORE DATAFILE '/u01/app/oracle/oradata/orcl/users01.dbf';
-- Recover the datafile
RECOVER DATAFILE '/u01/app/oracle/oradata/orcl/users01.dbf';
-- Bring tablespace online
ALTER TABLESPACE users ONLINE;
Terminal window
# Full database corruption check
rman target /
BACKUP VALIDATE DATABASE;
# Check specific datafile
BACKUP VALIDATE DATAFILE 4;
# Validate with detailed checking
BACKUP VALIDATE CHECK LOGICAL DATABASE;
# Generate list of all corrupted blocks
BLOCKRECOVER CORRUPTION LIST;
-- Create a procedure to salvage uncorrupted data
CREATE OR REPLACE PROCEDURE salvage_table_data(
p_table_name VARCHAR2,
p_owner VARCHAR2 DEFAULT USER
) IS
v_sql VARCHAR2(4000);
v_count NUMBER := 0;
v_error_count NUMBER := 0;
BEGIN
-- Create backup table
v_sql := 'CREATE TABLE ' || p_table_name || '_salvage AS ' ||
'SELECT * FROM ' || p_owner || '.' || p_table_name ||
' WHERE 1=0';
EXECUTE IMMEDIATE v_sql;
-- Salvage data row by row (for small tables)
FOR rec IN (SELECT ROWID FROM USER_OBJECTS WHERE ROWNUM <= 1000000) LOOP
BEGIN
v_sql := 'INSERT INTO ' || p_table_name || '_salvage ' ||
'SELECT * FROM ' || p_owner || '.' || p_table_name ||
' WHERE ROWID = ''' || rec.ROWID || '''';
EXECUTE IMMEDIATE v_sql;
v_count := v_count + 1;
EXCEPTION
WHEN OTHERS THEN
v_error_count := v_error_count + 1;
IF v_error_count > 100 THEN -- Stop if too many errors
EXIT;
END IF;
END;
END LOOP;
COMMIT;
DBMS_OUTPUT.PUT_LINE('Salvaged ' || v_count || ' rows');
DBMS_OUTPUT.PUT_LINE('Errors: ' || v_error_count);
END;
/
-- Check for zero blocks (blocks filled with zeros)
SELECT file#, block#, blocks, corruption_type
FROM v$database_block_corruption
WHERE corruption_type = 'CORRUPT';
-- RMAN can sometimes recover zero blocks
BLOCKRECOVER DATAFILE 4 BLOCK 123 FROM BACKUPSET;
Terminal window
# Check for hardware errors (Linux)
dmesg | grep -i error
cat /var/log/messages | grep -i "i/o error"
# Check disk health
smartctl -a /dev/sda
# Monitor storage performance
iostat -x 1 10
sar -d 1 10
-- Enable block checking
ALTER SYSTEM SET db_block_checking = FULL;
ALTER SYSTEM SET db_block_checksum = FULL;
-- Configure fast recovery area
ALTER SYSTEM SET db_recovery_file_dest = '/u01/fra';
ALTER SYSTEM SET db_recovery_file_dest_size = 10G;
-- Ensure archivelog mode
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;
Terminal window
# Schedule regular RMAN validation
rman target / <<EOF
RUN {
BACKUP VALIDATE DATABASE;
DELETE NOPROMPT EXPIRED BACKUP;
DELETE NOPROMPT OBSOLETE;
}
EXIT;
EOF
# Create monitoring script
#!/bin/bash
# corruption_check.sh
export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome_1
export ORACLE_SID=ORCL
# Check for new corruptions
sqlplus -s / as sysdba <<EOF > /tmp/corruption_check.log
SET PAGESIZE 0 FEEDBACK OFF
SELECT 'CORRUPTION DETECTED: File ' || file# || ' Block ' || block#
FROM v\$database_block_corruption;
EXIT;
EOF
# Send alert if corruption found
if [ -s /tmp/corruption_check.log ]; then
mail -s "Database Corruption Detected" [email protected] < /tmp/corruption_check.log
fi
-- Create corruption monitoring procedure
CREATE OR REPLACE PROCEDURE check_corruption AS
v_count NUMBER;
v_message VARCHAR2(4000);
BEGIN
SELECT COUNT(*) INTO v_count
FROM v$database_block_corruption;
IF v_count > 0 THEN
SELECT 'CORRUPTION ALERT: ' || COUNT(*) || ' corrupted blocks found. ' ||
LISTAGG('File ' || file# || ' Block ' || block#, ', ')
WITHIN GROUP (ORDER BY file#, block#)
INTO v_message
FROM v$database_block_corruption;
-- Log to alert log
EXECUTE IMMEDIATE 'BEGIN DBMS_SYSTEM.KSDWRT(2, ''' || v_message || '''); END;';
-- Insert into monitoring table
INSERT INTO corruption_alerts (alert_time, block_count, message)
VALUES (SYSDATE, v_count, v_message);
COMMIT;
END IF;
END;
/
-- Schedule regular checks
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'corruption_check_job',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN check_corruption; END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=HOURLY;INTERVAL=1',
enabled => TRUE
);
END;
/
-- Check database health metrics
SELECT name, value
FROM v$sysstat
WHERE name LIKE '%corrupt%' OR name LIKE '%checksum%';
-- Monitor I/O errors
SELECT file#, name, phyrds, phywrts, readtim, writetim
FROM v$filestat f, v$datafile d
WHERE f.file# = d.file#
ORDER BY readtim DESC, writetim DESC;
-- Check for recovery needs
SELECT file#, status, error, recover, fuzzy, checkpoint_change#
FROM v$datafile_header
WHERE status != 'ONLINE' OR recover = 'YES';
  1. Implement comprehensive backup strategy with RMAN
  2. Enable block checking and checksums for early detection
  3. Monitor hardware health proactively
  4. Use redundant storage (RAID, ASM) where possible
  5. Regular validation of database blocks
  6. Quick response procedures for corruption detection
  7. Test recovery procedures regularly
  8. Maintain proper documentation of recovery steps
  1. Don’t panic - corruption doesn’t always mean data loss
  2. Identify the scope of corruption (table, index, extent)
  3. Check if object is critical for business operations
  4. Attempt block media recovery first if in ARCHIVELOG mode
  5. Use RMAN block recovery as preferred method
  6. Consider object rebuild for indexes
  7. Document the incident and root cause analysis
  8. Review hardware and storage subsystem health

Block corruption is serious but often recoverable with proper procedures and backups. The key is early detection and having tested recovery procedures in place.