Why Do We Need Immutable Tables?
In many applications, certain data should never be modified once it is stored. Traditional tables allow UPDATE and DELETE operations, which can accidentally or intentionally change critical records.
Immutable tables solve this problem by allowing only INSERT operations and protecting data from modification or deletion until the configured retention period expires.
Common use cases include:
- Audit logs
- Financial transactions
- Compliance records (SOX, HIPAA, GDPR)
- Healthcare data
- Legal and government records
Immutable Tables in Oracle Database
Immutable tables are insert-only relational structures that enforce immutability through system-managed retention controls at both the table and row levels. These controls prohibit UPDATE and DELETE operations until the retention period expires.
While functionally similar to blockchain tables in terms of data immutability, immutable tables do not maintain cryptographic hash links between records.
Oracle introduced immutable tables in Oracle Database 19c Release Update 19.11, and they are supported in all later releases.
Prerequisites
The COMPATIBLE initialization parameter must be set to the appropriate value before immutable tables can be used.
[oracle@Primary ~]$ sqlplus / as sysdba
NOTE: Verify the database version and apply the appropriate COMPATIBLE value accordingly.
SQL> STARTUP
SQL> ALTER SYSTEM SET compatible=’19.11.0′ SCOPE=SPFILE;
System altered.
SQL> SHUT IMMEDIATE;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> STARTUP
ORACLE instance started.
Oracle Version Requirements
Immutable Tables were introduced in Oracle Database 19c RU 19.11.
Oracle 19.11 contains a few known issues related to retention policy modifications. These issues are resolved in Oracle 19.12 and later releases, including Oracle 21.3.
For production environments, Oracle recommends using the latest supported Release Update (RU).
Creating an Immutable Table
To create an immutable table, the IMMUTABLE keyword must be included in the CREATE TABLE statement.
In addition to this keyword, Oracle provides two immutable clauses that control data protection and retention behavior:
- NO DROP
- NO DELETE
NO DROP Clause (Table-Level Protection)
The NO DROP clause defines how long the table itself is protected from being dropped.
If the table contains no rows, it can still be dropped.
Unlike early implementations of blockchain tables, this clause also prevents the table from being removed using a DROP USER … CASCADE command.
Syntax
NO DROP [ UNTIL number DAYS IDLE ]
Options
NO DROP
Prevents the table from being dropped indefinitely.
Once data is inserted, the table becomes permanent.
This option should be used with caution, especially in test environments.
NO DROP UNTIL number DAYS IDLE
Prevents the table from being dropped until no new rows have been inserted for the specified number of days.
Each new insert resets the idle timer.
For testing purposes, a value of 0 or 1 day is often recommended.
NO DELETE Clause (Row-Level Protection)
The NO DELETE clause controls the row retention period, defining how long each row is protected from deletion after it is inserted.
Syntax
NO DELETE{
[ LOCKED ]
| (UNTIL number DAYS AFTER INSERT [ LOCKED ])
}
Options
NO DELETE
Retains each row permanently.
Although the absence of the LOCKED keyword may suggest that the retention policy can be modified, retention periods can only be increased and never reduced.
NO DELETE LOCKED
Functions the same as NO DELETE but explicitly locks the retention policy, preventing any future modification.
NO DELETE UNTIL number DAYS AFTER INSERT
Protects each row from deletion for the specified number of days after insertion.
The retention period can be increased later using the ALTER TABLE command.
The minimum allowed retention period is 16 days.
NO DELETE UNTIL number DAYS AFTER INSERT LOCKED
Protects each row for a fixed number of days after insertion and permanently locks the retention policy.
This setting cannot be changed using ALTER TABLE.
The minimum retention period is 16 days.
Example
CREATE IMMUTABLE TABLE imm_audit_log
(
id NUMBER,
action VARCHAR2(100),
log_date DATE)
NO DROP UNTIL 1 DAYS IDLE
NO DELETE UNTIL 30 DAYS AFTER INSERT;
This command creates an immutable table named IMM_AUDIT_LOG that allows only INSERT operations.
The table cannot be dropped until it has been idle (no new inserts) for one day, and each row is protected from deletion for 30 days after it is inserted.
UPDATE operations are not allowed, ensuring data remains tamper-proof during the retention period.
Hidden Columns in Immutable Tables
When an immutable table is created, Oracle automatically adds several hidden system-managed columns.
These columns are similar to those used in blockchain tables.
However, unlike blockchain tables, only a subset of these columns is actively populated.
You can view these columns using the USER_TAB_COLS view:
SELECT internal_column_id,
column_name,
data_type,
data_length,
hidden_column
FROM user_tab_cols
WHERE table_name = ‘IT_T1’ORDER BY internal_column_id;
Among the hidden columns:
- ORABCTAB_CREATION_TIME$and ORABCTAB_USER_NUMBER$ are populated.
- All other blockchain-related columns (hash, signature, chain ID, etc.) remain NULL.
This highlights a key difference between immutable tables and blockchain tables — immutable tables do not use cryptographic chaining.
Viewing Immutable Table Metadata
Oracle provides dedicated dictionary views to display immutable table metadata:
- USER_IMMUTABLE_TABLES
- ALL_IMMUTABLE_TABLES
- DBA_IMMUTABLE_TABLES
These views are based on the internal table:
SYS.IMMUTABLE_TABLE$
Example
SELECT row_retention,
row_retention_locked,
table_inactivity_retention
FROM user_immutable_tables
WHERE table_name = ‘IT_T1’;
This output shows:
- Row retention period (in days)
- Whether the retention policy is locked
- Table inactivity (idle) retention period
Altering an Immutable Table
Modifying the NO DROP Clause
According to documentation, the NO DROP clause can be modified using ALTER TABLE, provided the retention value is not reduced.
However, in Oracle 19c, this behavior is inconsistent.
For tables created with NO DROP UNTIL 0 DAYS IDLE, attempting to increase the value results in an error:
ALTER TABLE it_t1
NO DROP UNTIL 100 DAYS IDLE;
Error
ORA-05732: retention value cannot be lowered
Although the syntax is correct, this appears to be a bug in Oracle 19c.
This issue is resolved in 19.12 and later 21.3 releases.
Additionally, attempting to switch directly to NO DROP (maximum protection) results in an internal error in 19c:
ALTER TABLE it_t1
NO DROP;
Error
ORA-00600: internal error code [atbbctable_1]
This limitation makes testing risky, as starting with NO DROP can only be reversed by dropping the entire schema.
Modifying the NO DELETE Clause
If the retention policy is not locked, the row retention period can be increased but never reduced.
Example
Increase retention:
ALTER TABLE it_t1
NO DELETE UNTIL 32 DAYS AFTER INSERT;
Attempting to reduce it later fails:
ALTER TABLE it_t1
NO DELETE UNTIL 16 DAYS AFTER INSERT;
Error
ORA-05732: retention value cannot be lowered
Similarly, upgrading to NO DELETE (infinite retention) produces an internal error in Oracle 19c but works correctly in Oracle 21.3.
Restricted DML and DDL Operations
As expected for an insert-only structure, immutable tables block any operation that modifies or removes data.
Allowed
INSERT INTO it_t1
VALUES (1, ‘apple’, 20, SYSDATE);
COMMIT;
Not Allowed
- UPDATE
- DELETE
- TRUNCATE
- Adding columns
- Dropping columns
All such operations return:
ORA-05715: operation not allowed on the blockchain or immutable table
Allowed Schema Change
Increasing column length is permitted.
ALTER TABLE it_t1
MODIFY (fruit VARCHAR2(25));
DBMS_IMMUTABLE_TABLE Package
Expired rows cannot be removed using a normal DELETE statement.
Instead, Oracle provides the DBMS_IMMUTABLE_TABLE package.
Example
BEGIN dbms_immutable_table.delete_expired_rows(
schema_name => ‘testuser1’,
table_name => ‘it_t1’,
before_timestamp => NULL,
number_of_rows_deleted => :rows_deleted
);
END;
/
You can also restrict deletion using a timestamp condition.
Rows are deleted only if:
- They are beyond the retention period.
- They match the timestamp criteria.
Best Practices
- Use the latest Oracle 19c RU or later release.
- Choose retention periods carefully since they can only be increased.
- Avoid using NO DROP permanently in test environments.
- Monitor tablespace growth for long retention periods.
- Continue taking regular RMAN backups.
Performance Considerations
Immutable tables provide performance similar to regular heap tables for INSERT operations because they do not maintain cryptographic hash chains like blockchain tables. However, long retention periods can increase storage usage, so proper capacity planning is recommended.
Key Considerations
- Immutable tables prior to Oracle 21.3 exhibit multiple bugs and undocumented behaviors.
- They support indexing and partitioning like regular tables.
- Many restrictions applicable to blockchain tables also apply here.
- Immutable tables are ideal for insert-only, tamper-proof data storage.
- If cryptographic validation is required, blockchain tables may be a better choice.
When Should You Use Immutable Tables?
Use immutable tables when:
- You need regulatory compliance.
- Data must not be altered or deleted during a retention period.
- Audit integrity is required without the overhead of blockchain hashing.