ORA-01578 is raised when Oracle reads a data block whose contents fail internal validation. The block is marked corrupt and the read fails. The instance keeps running because corruption rarely crashes it, but every query touching that block errors until the block is repaired or bypassed.
Two risks follow. First, the data in that block is inaccessible or lost. Second, backups may be compromised: RMAN detects corrupt blocks during backup by default (MAXCORRUPT=0), but without proactive VALIDATE you may not know when corruption started or which backup pieces are clean.
The error is also frequently a false alarm on Data Guard standbys: NOLOGGING operations on the primary leave the standby with blocks Oracle reports as corrupt. Telling the two apart is the first decision in any ORA-01578 response.
This article covers read-only triage, the distinction between physical corruption and NOLOGGING-induced corruption, and the repair paths from Block Media Recovery through DBMS_REPAIR.
What this means
The error message names the file number and block number. ORA-01110 usually accompanies it with the datafile name. The block is not necessarily destroyed in the storage sense. It may have a bad checksum, a wrong block number, a scrambled header, or logical inconsistency in its row data.
Two diagnostic categories matter for response:
- Physical (media) corruption. The bytes on disk are wrong: checksum mismatch, wrong block number, zeroed block, torn write. Storage, host memory, or an Oracle bug is the usual root cause.
- Logical corruption. The block is structurally valid but internally inconsistent: row data, ITL entries, or row directories disagree. RMAN VALIDATE only catches this with CHECK LOGICAL.
A third category looks identical in the alert log but behaves differently: NOLOGGING-induced corruption. If ORA-26040 (“data block was loaded using NOLOGGING option”) accompanies ORA-01578, the block was loaded on the primary without redo, and a physical standby cannot reconstruct it. No hardware is failing, but the data is unrecoverable without reloading.
flowchart TD
A["ORA-01578 detected"] --> B{"ORA-26040 present?"}
B -- Yes --> C["NOLOGGING on standby"]
B -- No --> D["Media corruption"]
C --> E["RECOVER NONLOGGED BLOCK or reload"]
D --> F["RMAN VALIDATE CHECK LOGICAL"]
F --> G["V$DATABASE_BLOCK_CORRUPTION lists blocks"]
G --> H["BLOCKRECOVER or DBMS_REPAIR"]Common causes
| Cause | What it looks like | First thing to check |
|---|---|---|
| Storage hardware failure | ORA-01578 on blocks clustered in one LUN or extent range | OS logs, SMART, EDAC, V$DATABASE_BLOCK_CORRUPTION spread |
| Bad RAM | Corruption scattered across files, sometimes with ORA-00600 | mcelog, edac-utils, dmesg for ECC errors |
| NOLOGGING on primary, read on standby | ORA-01578 plus ORA-26040 on standby only; primary reads clean | V$DATAFILE.UNRECOVERABLE_TIME |
| Oracle bug | ORA-01578 with ORA-00600, often version-specific block format issue | Alert log arguments, My Oracle Support |
| Torn write after host crash | Single block, often following power loss or storage path failure | Block dump, RMAN VALIDATE |
| DB_BLOCK_CHECKING disabled | Corrupt block written to disk undetected; surfaces on later read | Current parameter value |
Quick checks
All read-only and safe to run during an incident.
-- Inventory every known corrupt block (populated by RMAN VALIDATE / ANALYZE / DBVERIFY)
SELECT FILE#, BLOCK#, BLOCKS, CORRUPTION_TYPE
FROM V$DATABASE_BLOCK_CORRUPTION;
-- Resolve file number to datafile name and status
SELECT FILE#, NAME, STATUS FROM V$DATAFILE WHERE FILE# = &file_num;
-- Pull recent ORA-01578 / ORA-01110 / ORA-26040 lines from the XML alert log
SELECT originating_timestamp, message_text
FROM V$DIAG_ALERT_EXT
WHERE message_text LIKE '%ORA-01578%'
OR message_text LIKE '%ORA-01110%'
OR message_text LIKE '%ORA-26040%'
ORDER BY originating_timestamp DESC;
-- Recent NOLOGGING exposure per datafile (standby diagnosis)
SELECT FILE#, UNRECOVERABLE_CHANGE#, UNRECOVERABLE_TIME
FROM V$DATAFILE
WHERE UNRECOVERABLE_TIME IS NOT NULL
ORDER BY UNRECOVERABLE_TIME DESC;
-- Was corruption already captured into a backup piece?
SELECT * FROM V$BACKUP_CORRUPTION WHERE COMPLETION_TIME > SYSDATE - 7;
-- Confirm proactive detection parameters
SELECT NAME, VALUE FROM V$PARAMETER
WHERE NAME IN ('db_block_checking', 'db_block_checksum');
How to diagnose it
Confirm whether the corruption is real or a NOLOGGING artifact. On a physical standby, check whether ORA-26040 accompanies ORA-01578. If it does, and the primary reads the same block without error, you have NOLOGGING-induced corruption, not media failure. Skip to the standby NOLOGGING fix path below.
Run RMAN VALIDATE to enumerate every corrupt block. A single ORA-01578 from the application tells you one block is bad. It does not tell you whether neighbors are also affected. Always validate before repairing.
# Validate the whole database (physical corruption only, default behavior)
rman target / <<'EOF'
VALIDATE DATABASE;
EOF
Add CHECK LOGICAL to also catch logical corruption:
# Physical plus logical corruption check
rman target / <<'EOF'
VALIDATE CHECK LOGICAL DATABASE;
EOF
Inspect CORRUPTION_TYPE in V$DATABASE_BLOCK_CORRUPTION. Values include ALL ZERO, FRACTURED, CORRUPT, and LOGICAL. Each type points to a different root cause.
Cross-check with DBVERIFY. DBVERIFY reads the datafile directly from disk, outside Oracle, so it can catch corruption the buffer cache might mask.
# Verify a specific datafile (safe on online files)
dbv file=/u01/oradata/prod/users01.dbf blocksize=8192
DBVERIFY output lists corrupt block ranges with explicit line markers.
Trace the corruption to a cause. Cluster the corrupt blocks by file and extent range. Random scatter across files points to memory or storage subsystem failure. A contiguous range in one file suggests a localized storage event. Check OS logs (
dmesg,/var/log/messages), SMART data, SAN multipath health, andmcelogfor ECC errors.Check whether your backups already captured the corruption. If
V$BACKUP_CORRUPTIONshows the corrupt block in a recent backup piece, that backup is compromised. Your last known-good backup may be older than expected.
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
V$DATABASE_BLOCK_CORRUPTION row count | Direct corruption inventory after VALIDATE | Any non-zero row |
| Alert log ORA-01578 / ORA-01110 / ORA-26040 | First-place detection of read failures | Any occurrence |
V$BACKUP_CORRUPTION | Whether backups captured bad blocks | Any rows |
V$COPY_CORRUPTION | Image copy integrity | Any rows |
V$DATAFILE.UNRECOVERABLE_TIME | NOLOGGING exposure on standby | Time newer than last incremental backup |
DB_BLOCK_CHECKING parameter | Proactive in-memory detection | FALSE in production |
| RMAN backup job status | Whether a recovery path still exists | Recent failures or no recent backup |
| OS storage and memory error counters | Hardware root cause | SMART reallocations, EDAC ECC errors |
Fixes
Physical corruption: Block Media Recovery
When you have a valid backup, Block Media Recovery (BMR) is the lowest-impact repair. RMAN recovers only the named blocks from backup plus archive redo, without taking the datafile or tablespace offline.
# Recover specific corrupt blocks
rman target / <<'EOF'
BLOCKRECOVER DATAFILE 5 BLOCK 1234, 1235, 1236;
EOF
Or recover every block listed in V$DATABASE_BLOCK_CORRUPTION:
rman target / <<'EOF'
BLOCKRECOVER CORRUPTION LIST;
EOF
Notes:
- BMR requires a valid backup and archive redo logs to roll the blocks forward to current SCN.
- BLOCKRECOVER removes repaired blocks from
V$DATABASE_BLOCK_CORRUPTIONon completion. Re-run VALIDATE to confirm before closing the incident. - If the corrupt block belongs to a critical object in SYSTEM, SYSAUX, or UNDO, engage Oracle Support before improvising.
NOLOGGING-induced corruption on standby
This is the most common ORA-01578 false positive. The primary loaded data with NOLOGGING (direct-path insert, certain DDL, CREATE TABLE AS SELECT with no logging). Redo was not generated for those blocks, so the standby cannot reconstruct them.
On 12.2 and later, RMAN can recover only the nonlogged blocks without shipping the whole datafile:
# On the standby
rman target / <<'EOF'
RECOVER DATABASE NONLOGGED BLOCK;
EOF
On versions prior to 12.2, restore the affected datafile from the primary, or take a fresh incremental backup on the primary and apply it to the standby.
Prevention: set ALTER DATABASE FORCE LOGGING on the primary, or follow any NOLOGGING operation with an incremental backup that is shipped to and applied on the standby.
DBMS_REPAIR when no clean backup exists
Warning: DBMS_REPAIR does not fix corruption. It marks blocks as software-corrupt so DML can skip them. Data in those blocks is permanently lost. Use only when BMR is impossible and the data loss is documented and accepted.
-- One-time setup: repair and orphan key tables
EXEC DBMS_REPAIR.ADMIN_TABLES('REPAIR_TAB', 1, 1, 'USERS');
EXEC DBMS_REPAIR.ADMIN_TABLES('ORPHAN_TAB', 2, 1, 'USERS');
-- Scan a specific object and record corrupt blocks
EXEC DBMS_REPAIR.CHECK_OBJECT('HR', 'EMPLOYEES', NULL, 1, 'REPAIR_TAB');
-- Mark blocks so DML skips them
EXEC DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('HR', 'EMPLOYEES');
Rebuild affected indexes afterward, as orphaned index entries will remain.
Data Recovery Advisor
Historically, RMAN’s Data Recovery Advisor (DRA) provided LIST FAILURE, ADVISE FAILURE, and REPAIR FAILURE automation for corruption incidents. DRA was deprecated in 19c and is desupported in 26ai with no replacement. Do not build new runbooks around DRA if you are on, or plan to upgrade to, 26ai.
Prevention
- Enable DB_BLOCK_CHECKING. Default is FALSE. Set to MEDIUM or FULL in production. Overhead is roughly 1-10% CPU, but it catches corruption in memory before it reaches disk.
- Confirm DB_BLOCK_CHECKSUM is TYPICAL or FULL. Default is TYPICAL. Checksums catch the majority of media corruption on read.
- Schedule regular RMAN VALIDATE runs.
VALIDATE CHECK LOGICAL DATABASEweekly catches corruption before it reaches your backup window. Treat it as a backup job: monitor for completion. - Set FORCE LOGGING on primary databases with physical standbys. NOLOGGING is the single largest source of standby ORA-01578 plus ORA-26040.
- Track V$DATAFILE.UNRECOVERABLE_TIME. If it is newer than your last incremental backup, the standby has unrecoverable blocks.
- Monitor storage and memory health at the OS level. SMART reallocated sector counts, EDAC ECC errors, and SAN path failures precede most real corruption incidents.
- Test backup recovery quarterly. A backup that completes successfully is not the same as a backup that restores. The first time most teams discover their backups are bad is during a real disaster.
How Netdata helps
ORA-01578 surfaces in the alert log, but the surrounding context (storage errors, memory errors, recent NOLOGGING activity, backup health) determines the repair path. Netdata correlates these signals on a per-second timeline:
- Alert log parsing surfaces ORA-01578, ORA-01110, and ORA-26040 entries with file and block numbers.
- OS-level storage metrics (disk error rates, SMART attributes where exposed) let you pin the corruption timestamp to hardware events.
- Memory ECC counters from EDAC and kernel MCE logs help confirm or rule out bad RAM.
- RMAN backup job status from
V$RMAN_BACKUP_JOB_DETAILSconfirms whether your recovery path is intact. V$DATAFILE.UNRECOVERABLE_TIMEtrending flags NOLOGGING exposure before failover turns it into an incident.V$DATABASE_BLOCK_CORRUPTIONrow count as a gauge charts repair progress toward zero.
See Oracle Database monitoring with Netdata for setup.
Related guides
- How Oracle Database actually works in production: a mental model for operators
- Oracle archive log destination full: V$ARCHIVE_DEST_STATUS, the ERROR state, and space
- Oracle autoextend hit MAXSIZE: the space gotcha with a half-empty filesystem
- Oracle blocking sessions: finding the blocker at the head of the chain
- Oracle ‘Thread N cannot allocate new log’: the archive hang that masquerades as up






