Resolving ORA-01555 Error: Snapshot Too Old (KBA1827)
At a Glance
ORA Error: | ORA-01555: Snapshot Too Old | |
---|---|---|
Root Cause: | The root cause of ORA-01555 is that UNDO is not present to satisfy a read-consistent request. This can be because of either one of two reasons:
Related to masking, this can happen as a result of one of the following cases:
|
|
Best Practices: | There are some Best Practices for an Oracle masking job. These points will also reduce the chance of encountering ORA-01555.
|
|
Solution 1 or 2? |
This depends on what caused the ORA-01555:
|
|
Solution 1: Delayed Block Cleanout |
If the table is configured according to Best Practice, and a large DML transaction had been performed on the database earlier then these steps are needed. Delayed Block Cleanout is the process where Oracle completes a block cleanup after the transaction commits. Some notes about the SQL below:
|
|
Solution 2: Manage UNDO Tablespace |
If solution 1 fails then the UNDO Tablespace size is too small or the Retention too short. The action here is to increase the size of the UNDO tablespace or create a new and bigger UNDO Tablespace or to change the UNDO Retention. If the masked database is a vDB, then there are two options to change the UNDO Tablespce:
See note below to check UNDO tablespace size. For more details, contact your DBA for assistance. |
Applicable Delphix Versions
- Click here to view the versions of the Delphix engine to which this article applies
-
Major Release All Sub Releases 6.0 6.0.0.0, 6.0.1.0, 6.0.1.1, 6.0.2.0, 6.0.3.0, 6.0.3.1, 6.0.4.0 5.3
5.3.0.0, 5.3.0.1, 5.3.0.2, 5.3.0.3, 5.3.1.0, 5.3.1.1, 5.3.1.2, 5.3.2.0, 5.3.3.0, 5.3.3.1, 5.3.4.0, 5.3.5.0 5.3.6.0, 5.3.7.0, 5.3.7.1, 5.3.8.0, 5.3.8.1, 5.3.9.0 5.2
5.2.2.0, 5.2.2.1, 5.2.3.0, 5.2.4.0, 5.2.5.0, 5.2.5.1, 5.2.6.0, 5.2.6.1
5.1
5.1.0.0, 5.1.1.0, 5.1.2.0, 5.1.3.0, 5.1.4.0, 5.1.5.0, 5.1.5.1, 5.1.6.0, 5.1.7.0, 5.1.8.0, 5.1.8.1, 5.1.9.0, 5.1.10.0
5.0
5.0.1.0, 5.0.1.1, 5.0.2.0, 5.0.2.1, 5.0.2.2, 5.0.2.3, 5.0.3.0, 5.0.3.1, 5.0.4.0, 5.0.4.1 ,5.0.5.0, 5.0.5.1, 5.0.5.2, 5.0.5.3, 5.0.5.4
4.3
4.3.1.0, 4.3.2.0, 4.3.2.1, 4.3.3.0, 4.3.4.0, 4.3.4.1, 4.3.5.0
4.2
4.2.0.0, 4.2.0.3, 4.2.1.0, 4.2.1.1, 4.2.2.0, 4.2.2.1, 4.2.3.0, 4.2.4.0 , 4.2.5.0, 4.2.5.1
4.1
4.1.0.0, 4.1.2.0, 4.1.3.0, 4.1.3.1, 4.1.3.2, 4.1.4.0, 4.1.5.0, 4.1.6.0
Issue
ORA-01555 is a complex error. Note that this is not a complete overview of ORA-01555, there can also be other factors that are not detailed in this document that can cause the error.
Two scenarios explained:
- An earlier DML transaction caused the issue:
This happens in any job and is due to an earlier large DML and Delayed Block Cleanout. - Current DML transactions caused the issue:
This is unlikely in a masking job configured according to the Best Practice. No other DML transactions should be executed while running the masking job.
Delayed Block Cleanout
For a masking job, this is the likely cause. The ORA-01555 may occur because of Delayed Block Cleanout… which is caused by an earlier large transaction (for example UPDATE, INSERT, and DELETE) on the masked table(s).
This article goes through both these scenarios and what to do to resolve these issues.
Not enough UNDO
This is unlikely the cause when using masking. The root cause here is that data is being changed at the same time it’s being read, and there is insufficient UNDO to satisfy read-consistent requests.
However, on an optimal masking job, this should not happen, as the SELECT statement is fetching 'virgin' unmasked blocks.
Best Practice and 'Optimal' Masking Job
The diagram below shows an 'Optimal' Masking Job in progress. Each rectangle represents an Oracle data block.
The fetch in the SELECT will read the data. On an optimal masking job, this will be using a Full Table Scan (FTS) and block after block is read (the order of the block). After masking transformation, the rows are updated and Oracle stores the original values in the UNDO Segment.
This means we can mask as many rows as we want - the Masked Committed values (pictured green) will never be touched after the commit and the SELECT will always fetch 'virgin' unmasked data (white below).
On an Optimal Masking Job:
- Use 'ROWID' as Logical Key - this will ensure Full Table Scan (FTS).
- No 'WHERE' or 'ORDER BY' which will otherwise change the row order - this will ensure Full Table Scan (FTS).
- No indexes on masked columns - having indexes will make changes in additional Oracle data blocks used for indexes.
- Ensure that there is no external transaction running which will change the data on the masked table.
- Ensure Delayed Block Cleanout has been performed on all tables
In the example, there are 18 grey blocks which are around 18,000 rows. These are loaded into the masking engine and buffered between the masking steps. The 'x' and 'y' is just added to indicate motion ('x' unmasked and 'y' is masked data). The Transaction has Updated around 8,000 rows out of 10,000 (default Commit Size) but not yet committed (these records are highlighted in orange above).
Masking Execution with ORA-01555
What happens when the Oracle database throws ORA-01555?
There are a few key points here:
- SELECT
- It is the SELECT that causes ORA-01555.
- As discussed, this happens due to one of these two reasons:
- Current DML transactions caused the issue:
- This is unlikely in a masking job configured according to the Best Practice.
- An earlier DML transaction caused the issue:
- This happens in any job and is due to an earlier large DML and Delayed Block Cleanout.
- Current DML transactions caused the issue:
Solution
The solution is to always run masking jobs:
- in accordance with the Best Practice; and
- ensure sufficient UNDO tablespace (retention and size); and
- Performed Delayed Block Cleanout on all tables prior to running the masking job.
The Following Block Cleanout SQL Script will force a Delayed Block Cleanout.
- The script can be executed before on the tables (recommended before dSource ingestion) or be executed as a Pre-Script in the masking job.
- All tables might need to be added in the script.
ALTER session SET events '10949 trace name context forever, level 1'; SELECT count(*) FROM (SELECT ROWID FROM [TABLE_with_ORA-01555]); SELECT count(*) FROM (SELECT ROWID FROM [TABLE_with_ORA-01555]); SELECT count(*) FROM (SELECT ROWID FROM [TABLE_with_ORA-01555]); ...
SQL to check UNDO Tablespace Size
To check the size of the UNDO tablespace, please use this query:
- Best is to have Autoextend,
- Make sure Max has not been reached.
SELECT tablespace_name, file_id, bytes/1024/1024/1024 Size_GB, maxbytes/1024/1024/1024 Max_GB, autoextensible FROM dba_data_files WHERE tablespace_name IN (SELECT tablespace_name FROM dba_tablespaces WHERE contents='UNDO');