blockrecover is an experimental Rust proof of concept for single-block
recovery in Oracle Database Standard Edition environments. It explores how a
block restored from an RMAN backup can be advanced with archived redo without
invoking Oracle's block media-recovery facility.
Caution
This repository contains experimental research code for disposable, isolated laboratory systems only. It is not production-ready, supported, or endorsed by Oracle. It can corrupt datafiles, prevent a database from opening, or cause permanent data loss and downtime. Do not use it with production systems or valuable data. The author provides no warranty, accepts no responsibility, and shall not be liable for any loss, corruption, outage, or other damage arising from its use. Anyone running the software assumes all risk and must maintain independent, tested backups.
The current implementation targets Oracle Database 19.25 on Linux AArch64 and
has been exercised against one controlled test database. It is a narrow
laboratory prototype, not a general replacement for RMAN BLOCKRECOVER.
The program does not call Oracle's block media-recovery API. In automatic mode it uses:
- SQL*Plus to resolve the datafile and establish a stable archived-redo boundary;
- RMAN to restore a full backup datafile to a separate path and, when necessary, restore missing archived logs;
- its own redo reader and physical block applier to recover one block;
- RMAN to uncatalog temporary copies;
- an interactive, explicitly destructive installation state machine;
- RMAN
VALIDATE DATAFILE ... BLOCK ...to validate the installed block.
Candidate generation is non-destructive. The active datafile is modified only
after the user types the exact confirmation word INSTALL. That guard reduces
the chance of an accidental write; it does not make installation safe.
Use this repository only to:
- study Oracle block and archived-redo behavior in a disposable lab;
- reproduce the documented Oracle 19.25/AArch64 test case;
- review and extend the fail-closed parser against independently verified samples;
- evaluate a conceptual Standard Edition recovery workflow when complete database backups are available.
Do not use it as an operational recovery product, as a substitute for Oracle Support, or as the only copy of recoverable data.
cargo build --release
cp target/release/blockrecover .The runtime Oracle account must be able to execute:
sqlplus -L -s / as sysdba
rman target /
On aarch64-unknown-linux-gnu, the repository's Cargo configuration uses the
LLD shipped with the active Rust toolchain while retaining cc as the driver.
This avoids depending on the host's BFD linker and preserves the normal Oracle
Linux system-library search paths.
The requested interface is the default:
./blockrecover \
--file /path/to/oracle/datafile.dbf \
--block 38452The program creates a unique work directory in the current directory. An explicit location is usually preferable:
./blockrecover \
--file /u01/app/oracle/oradata/RICK/.../o1_mf_sysaux_....dbf \
--block 38452 \
--work-dir /u02/recovery/f14-b38452Artifacts:
f14-b38452/
├── restored-f14.dbf
├── recovered-f14-b38452.bin
├── original-f14-b38452-before-install.bin # created only after confirmation
└── archivelogs/
└── t1-s492/
└── 1_492_<resetlogs-id>.dbf
restored-f14.dbf is the full backup datafile with the selected block advanced
by the standalone recovery engine. recovered-f14-b38452.bin is the exact
database-block-sized image intended for installation. The remaining blocks in
the restored datafile are still at their backup checkpoint and must not replace
the live datafile.
Automatic mode performs ALTER SYSTEM ARCHIVE LOG CURRENT. This converts the
live redo boundary into stable archived-log input. It records CURRENT_SCN
before the switch and ignores records newer than that SCN.
After producing the candidate, the program prints a high-visibility warning:
DANGER: DIRECT ORACLE DATAFILE MODIFICATION
...
The COMPLETE Oracle instance will be shut down before the write.
...
Type exactly INSTALL to continue:
Any response other than uppercase INSTALL, including EOF or an empty line,
declines installation. The recovered artifacts remain available for inspection.
Use --inspect to print every parsed target change vector and its field bytes.
Use --until-scn N for a deterministic earlier recovery boundary.
| Option | Mode | Meaning |
|---|---|---|
--file PATH |
both | Target active datafile in automatic mode; offline copy in manual mode |
--block N |
both | Zero-based physical database block number |
--work-dir PATH |
automatic | New artifact directory; an existing directory is rejected |
--until-scn N |
automatic | Recovery boundary captured before the log switch |
--sqlplus PATH |
automatic | SQL*Plus executable, default sqlplus |
--rman PATH |
automatic | RMAN executable, default rman |
--redo PATH |
manual | Redo file; repeat in physical sequence order |
--block-size N |
manual | Database block size, default 8192 |
--output PATH |
manual | New full datafile-copy output |
--in-place |
manual | Modify the supplied offline copy |
--inspect |
both | Print RMAN output and complete target-vector fields |
Manual mode is useful for repeatable offline analysis:
./blockrecover \
--file /tmp/restored-f14.dbf \
--block 38452 \
--redo /archive/1_492.arc \
--redo /archive/1_493.arc \
--output /tmp/recovered-f14.dbf \
--inspect--in-place is accepted only in manual mode and must point to a disposable
offline copy. Without --in-place, an existing output is never overwritten.
Installation is part of automatic mode, but only after explicit confirmation. The complete instance is stopped; stopping only the PDB is not considered a sufficient cache boundary. The implementation performs:
SHUTDOWN IMMEDIATE;- an independent instance probe requiring ORA-01034/ORA-27101;
- a raw DBA, file identity, candidate checksum, and SCN regression check;
- preservation of the exact original block with
create_newandfsync; - positional candidate write, full-datafile
fsync, reread, and all-byte comparison; STARTUP MOUNT;- a second
V$DATAFILEidentity check; VALIDATE DATAFILE <file#> BLOCK <block#>;- rejection of RMAN
FAILED, nonzero failing blocks, or any overlappingV$DATABASE_BLOCK_CORRUPTIONrow; ALTER DATABASE OPENonly after successful validation.
If the write/reread fails while Oracle is down, the preserved original bytes are restored. If RMAN validation fails, the mounted instance is stopped, the original block is restored offline, and normal startup is attempted. If the database cannot be proven offline, no filesystem write is attempted.
For a plain filesystem datafile in a controlled lab, the conceptual write is:
offset = block_number * block_size
= 38452 * 8192
= 314998784
Never copy the whole RMAN-restored datafile over the active one. Only the single, recovered block image is installed.
- Installation causes a complete database outage, not only a PDB outage.
SHUTDOWN IMMEDIATE,STARTUP MOUNT, RMAN validation, and database open all run under local OS-authenticated SYSDBA.- A killed process after shutdown leaves the candidate and original image in the work directory. Keep Oracle down until their state is inspected.
- The installation path assumes a plain filesystem datafile. ASM, raw devices, encrypted blocks, and storage snapshots require a different writer and are outside the implemented boundary.
- The prompt can receive
INSTALLfrom a pipe for controlled automation, but doing so bypasses the human pause and should be restricted operationally.
The engine is intentionally fail-closed.
| Area | Status |
|---|---|
| Oracle release/layout | 19.25, Linux AArch64, compact SCNs |
| Database block | 8 KiB smallfile type-6 heap block |
| Redo block framing | 512, 1024, or 4096 bytes |
| Redo source | archived redo; online redo parser also rejects stale reused tail |
| Transaction model | committed conventional transaction with terminal OP:5.4 |
| Row operation | OP:11.5 ordinary uncompressed single row-piece update |
| Row format | 0x2c H-FL row, ordinary/extended lengths and NULL markers |
| ITL | existing ITL entry, physical KTB F/cleanout handling |
| Integrity | expected prior block SCN, RBA order, DBA, checksum, and redo-chain checks |
| RAC/multiple redo threads | rejected |
| INSERT/DELETE/QMI/overwrite | rejected |
| Chained/migrated row pieces | rejected |
| Index, LOB, compressed/encrypted blocks | rejected |
| Rolled-back or incomplete transactions | rejected |
This is a working proof of concept for the validated laboratory case, not a general replacement for Oracle recovery. Encountering an unsupported target vector, missing transaction boundary, redo gap, unexpected heap layout, or bad checksum terminates recovery without producing a silently guessed block.
The end-to-end vrick19 test began with backup block SCN 101058383,
restored archived log sequence 492 from an RMAN backup, then read sequences
493–496. Two target OP:11.5 vectors were applied:
RBA 000001ed.0000b997.0010: salary 48000 -> 48001
RBA 000001ee.000006e9.0010: salary 48001 -> 48000
The generated block and Oracle's independently captured reference block had the same complete 8192-byte SHA-256:
24b226d4e5aa16461a527d777d1a5ae44a17662dac1e6bdd4d9ed23e2f00d871
cmp reported no differences. DBVERIFY examined only block 38452 and
reported zero failing/corrupt pages and highest block SCN 102044940.
Temporary datafile and archived-log copies were absent from V$DATAFILE_COPY
and V$ARCHIVED_LOG after the automatic uncatalog step.
The destructive installation test additionally proved:
candidate SHA-256 = installed reread SHA-256
24b226d4e5aa16461a527d777d1a5ae44a17662dac1e6bdd4d9ed23e2f00d871
RMAN:
File Status Marked Corrupt Blocks Examined High SCN
14 OK 0 1 102044940
Data Blocks Failing: 0
V$DATABASE_BLOCK_CORRUPTION rows for file 14/block 38452: 0
Database OPEN_MODE: READ WRITE
PDB RICK2: READ WRITE
HR.EMPLOYEES employee 100 salary: 48000
See docs/PHYSICAL_RECOVERY.md for the byte layouts, recovery algorithms, validation rules, and implementation pseudocode. See docs/OPERATIONS.md for the complete operator runbook, prompt behavior, validation criteria, rollback paths, and post-run checks.