0% found this document useful (0 votes)
80 views9 pages

ORA-01555: "Snapshot Too Old" - Overview: 1. Fewer and Smaller Rollback Segments For A Very Actively Changing Database

The document discusses the Oracle database error ORA-01555 "Snapshot too old" and provides explanations of the situations that commonly cause this error. It describes how Oracle uses system change numbers, rollback segments, and read consistency to reconstruct snapshots of data at a point in time for queries. The error occurs when a query tries to access a snapshot from a rollback segment that has been overwritten due to space reuse, a corrupted segment, or fetching data across transactions that were committed.

Uploaded by

Pankaj Sharma
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
80 views9 pages

ORA-01555: "Snapshot Too Old" - Overview: 1. Fewer and Smaller Rollback Segments For A Very Actively Changing Database

The document discusses the Oracle database error ORA-01555 "Snapshot too old" and provides explanations of the situations that commonly cause this error. It describes how Oracle uses system change numbers, rollback segments, and read consistency to reconstruct snapshots of data at a point in time for queries. The error occurs when a query tries to access a snapshot from a rollback segment that has been overwritten due to space reuse, a corrupted segment, or fetching data across transactions that were committed.

Uploaded by

Pankaj Sharma
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 9

ORA-01555: "Snapshot too old" - Overview

There are various reasons why customers can get the error ORA-01555. Sometimes it is due to rollback
segments being too small in size, but there are other reasons. This bulletin is an attempt to give a
complete summary of all the situations which would cause an ORA-01555 error and how to resolve them.
In order to understand the bulletin, one needs to understand some of the internal mechanisms of Oracle,
so we start by explaining briefly about read consistency and block cleanouts.

Oracle always enforces statement-level read consistency. This guarantees that the data returned by a
single query is consistent with respect to time when the query began. Therefore, a query never sees the
data-changes made by transactions that commit during the course of execution of the query.

Oracle uniquely identifies any given point in time by a set of numbers called the System Change Numbers
(SCN). So SCN can be defined as the state of the database at any one given point in time. To produce
read-consistency, Oracle marks the current SCN as the query enters the execution phase. The query can
only see the snapshot of the records as they were at the time of marked SCN.

Oracle uses rollback segments to reconstruct the read-consistent snapshot of the data. Whenever a
transaction makes any changes, a snapshot of the record before the changes were made is copied to a
rollback segment and the data block header is marked appropriately with the address of the rollback
segment block where the changes are recorded. The data block also maintains the SCN of the last
committed change to the block.

As the data blocks are read on behalf of the query, only blocks with lower SCN than the query SCN will
be read. If a block has uncommitted changes of other transactions or changed data with more recent
SCN, then the data is reconstructed using the saved snapshot from the rollback segments. In some rare
situations, if RDBMS is not able to reconstruct the snapshot for a long running query, the query results in
an ORA-01555 error.

A rollback segment maintains the snapshot of the changed data as long as the transaction is still active
(commit or rollback has not been issued). Once a transaction is committed, RDBMS marks it with current
SCN and the space used by the snapshot becomes available for reuse.

Therefore, ORA-01555 will result if the query is looking for the snapshot  which is so old that rollback
segment information could not be found because of wrap around or overwrite.

Situations Where ORA-01555 Errors Commonly Occur

1. Fewer and smaller rollback segments for a very actively changing database

If the database has many transactions changing data and commiting very often, then the chance of
reusing the space used by a committed  transaction is higher. A long running query then may not be able
to  reconstruct the snapshot due to wrap around and overwrite in rollback  segments. Larger rollback
segments in this case will reduce the chance  of reusing the committed transaction slots.

2. Corrupted rollback segment

If the rollback segment is corrupted and could not be read, then a statement needing to reconstruct a
before image snapshot will result in the error.

3. Fetch across commit

This is the situation when a query opens a cursor, then loops through fetching, changing, and committing
the records on the same table. In this scenerio, very often an ORA-01555 can result. Let's take the 
following example to explain this:

A cursor was opened at SCN=10. The execution SCN of the query is  then marked as SCN=10. Every
fetch by that cursor now needs to get the read-consistent data from SCN=10. The user program is now 
fetching x numbers of records, changing them, and committing them. Let's say they were committed with
SCN=20. If a later fetch happens to retrieve a record which is in one of the previously committed  blocks,
then the fetch will see that the SCN there as 20. Since the fetch has to get the snapshot from SCN=10 it
will try to find it in the rollback segments. If it could rollback sufficiently backwards  as previously
explained, then it could reconstruct the snapshot  from SCN=10. If not, then it will result in an ORA-01555
error.

Committing less often which will result in larger rollback segments will REDUCE the probability of getting
'snapshot too old' error.

4. Fetch across commits with delayed block clean out

To complicate things, now we see how delayed block clean outs play an important role in getting this
error.

When a data or index block is modified in the database and the transaction committed, Oracle does a fast
commit by marking the transaction as committed in the rollback segment header but does not clean the
datablocks that were modified. The next transaction which does a select on the  modified blocks will do
the actual cleanout of the block. This is known  as a delayed block cleanout.

Now, take the same scenario as described in previous section. But instead  of assuming one table, let us
assume that there are two tables in question. i.e: the cursor is opened and then in a loop, it fetches from
one table and changes records in another, and commits. Even though the records are  getting committed
in another table it could still cause ORA-01555 because  cleanout has not been done on the table from
which the records are being  fetched.

For this case, a full table scan before opening and fetching through the cursor will help.

Summary:

Fetches across commits as explained in the last two cases are not supported by ANSI standard.
According to ANSI standard a cursor is invalidated when a commit is performed and should be closed and
reopened. Oracle allows users to do fetch across commits but users should be aware that it might result
in ORA-01555.
ORA-01555 "Snapshot too old" - Detailed Explanation

Terminology

Two key concepts are briefly covered below which help in the understanding of ORA-01555, Read
Consistency and Delayed Block Cleanout.

1. Read Consistency

This is documented in the Oracle Database Concepts manual and so will not be discussed further.
However, for the purposes of this article this should be read and understood if not understood already.
Oracle Server has the ability to have multi-version read consistency which is invaluable to you because it
guarantees that you are seeing a consistent view of the data (no 'dirty reads').

2. Delayed Block Cleanout

This is best illustrated with an example: Consider a transaction that updates a million row table. This
obviously visits a large number of database blocks to make the change to the data. When the user
commits the transaction Oracle does NOT go back and revisit these blocks to make the change
permanent. It is left for the next transaction that visits any block affected by the update to 'tidy up' the
block (hence the term 'delayed block cleanout').

Whenever Oracle changes a database block (index, table, cluster) it stores a pointer in the header of the
data block which identifies the rollback segment used to hold the rollback information for the changes
made by the transaction. (This is required if the user later elects to not commit the changes and wishes to
'undo' the changes made.)

Upon commit, the database simply marks the relevant rollback segment header entry as committed. Now,
when one of the changed blocks is revisited Oracle examines the header of the data block which
indicates that it has been changed at some point. The database needs to confirm whether the change has
been committed or whether it is currently uncommitted. To do this, Oracle determines the rollback
segment used for the previous transaction (from the block's header) and then determines whether the
rollback header indicates whether it has been committed or not.

If it is found that the block is committed then the header of the data block is updated so that subsequent
accesses to the block do not incur this processing.

This behaviour is illustrated in a very simplified way below. Here we walk through the stages involved in
updating a data block.

Stage 1 - No Changes Made

Description: This is the starting point. At the top of the data block we have an area used to link active
transactions to a rollback segment (the 'tx' part), and the rollback segment header has a table that stores
information upon all the latest transactions that have used that rollback segment.

In our example, we have two active transaction slots (01 and 02) and the next free slot is slot 03. (Since
we are free to overwrite committed transactions.)
Stage 2 - Row 2 is Updated

Description: We have now updated row 2 of block 500. Note that the data block header is updated to
point to the rollback segment 5, transaction slot 3 (5.3) and that it is marked uncommitted (Active).

Stage 3 - The User Issues a Commit

Description: Next the user hits commit. Note that all that this does is it updates the rollback segment
header's corresponding transaction slot as committed. It does *nothing* to the data block.

Stage 4 - Another User Selects Data Block 500

Description: Some time later another user (or the same user) revisits data block 500. We can see that
there is an uncommitted change in the data block according to the data block's header.

Oracle then uses the data block header to look up the corresponding rollback segment transaction table
slot, sees that it has been committed, and changes data block 500 to reflect the true state of the
datablock. (i.e. it performs delayed cleanout).
ORA-01555 Explanation

There are two fundamental causes of the error ORA-01555 that are a result of Oracle trying to attain a
'read consistent' image. These are:

 The rollback information itself is overwritten so that Oracle is unable to rollback the (committed)
transaction entries to attain a sufficiently old enough version of the block.
 The transaction slot in the rollback segment's transaction table (stored in the rollback segment's
header) is overwritten, and Oracle cannot rollback the transaction header sufficiently to derive the
original rollback segment transaction slot.

Both of these situations are discussed below with the series of steps that cause the ORA-01555. In the
steps, reference is made to 'QENV'. 'QENV' is short for 'Query Environment', which can be thought of as
the environment that existed when a query is first started and to which Oracle is trying to attain a read
consistent image. Associated with this environment is the SCN (System Change Number) at that time and
hence, QENV 50 is the query environment with SCN 50.

Case 1 - Rollback Overwritten

This breaks down into two cases: another session overwriting the rollback that the current session
requires or the case where the current session overwrites the rollback information that it requires. The
latter is discussed in this article because this is usually the harder one to understand.

1. Session 1 starts query at time T1 and QENV 50


2. Session 1 selects block B1 during this query
3. Session 1 updates the block at SCN 51
4. Session 1 does some other work that generates rollback information.
5. Session 1 commits the changes made in steps '3' and '4'. (Now other transactions are free to
overwrite this rollback information)
6. Session 1 revisits the same block B1 (perhaps for a different row).

Now, Oracle can see from the block's header that it has been changed and it is later than the required
QENV (which was 50). Therefore we need to get an image of the block as of this QENV.

If an old enough version of the block can be found in the buffer cache then we will use this, otherwise we
need to rollback the current block to generate another version of the block as at the required QENV.

It is under this condition that Oracle may not be able to get the required rollback information because
Session 1's changes have generated rollback information that has overwritten it and returns the ORA-
1555 error.

Case 2 - Rollback Transaction Slot Overwritten


1. Session 1 starts query at time T1 and QENV 50
2. Session 1 selects block B1 during this query
3. Session 1 updates the block at SCN 51
4. Session 1 commits the changes (Now other transactions are free to overwrite this rollback
information)
5. A session (Session 1, another session or a number of other sessions) then use the same rollback
segment for a series of committed transactions.
These transactions each consume a slot in the rollback segment transaction table such that it
eventually wraps around (the slots are written to in a circular fashion) and overwrites all the slots.
Note that Oracle is free to reuse these slots since all transactions are committed.
6. Session 1's query then visits a block that has been changed since the initial QENV was
established. Oracle therefore needs to derive an image of the block as at that point in time.

Next Oracle attempts to lookup the rollback segment header's transaction slot pointed to by the top of the
data block. It then realises that this has been overwritten and attempts to rollback the changes made to
the rollback segment header to get the original transaction slot entry.

If it cannot rollback the rollback segment transaction table sufficiently it will return ORA-1555 since Oracle
can no longer derive the required version of the data block.

It is also possible to encounter a variant of the transaction slot being overwritten when using block
cleanout. This is briefly described below:

Session 1 starts a query at QENV 50. After this another process updates the blocks that Session 1 will
require. When Session 1 encounters these blocks it determines that the blocks have changed and have
not yet been cleaned out (via delayed block cleanout). Session 1 must determine whether the rows in the
block existed at QENV 50, were subsequently changed.

In order to do this, Oracle must look at the relevant rollback segment transaction table slot to determine
the committed SCN. If this SCN is after the QENV then Oracle must try to construct an older version of
the block and if it is before then the block just needs clean out to be good enough for the QENV.

If the transaction slot has been overwritten and the transaction table cannot be rolled back to a sufficiently
old enough version then Oracle cannot derive the block image and will return ORA-1555.

Note: Normally Oracle can use an algorithm for determining a block's SCN during block cleanout even
when the rollback segment slot has been overwritten. But in this case Oracle cannot guarantee that the
version of the block has not changed since the start of the query.

Solutions

This section lists some of the solutions that can be used to avoid the ORA-01555 problems discussed in
this article. It addresses the cases where rollback segment information is overwritten by the same session
and when the rollback segment transaction table entry is overwritten.

It is worth highlighting that if a single session experiences the ORA-01555 and it is not one of the special
cases listed at the end of this article, then the session must be using an Oracle extension whereby
fetches across commits are tolerated. This does not follow the ANSI model and in the rare cases where
ORA-01555 is returned one of the solutions below must be used.

Case 1 - Rollback Overwritten


1. Increase size of rollback segment which will reduce the likelihood of overwriting rollback
information that is needed.
2. Reduce the number of commits (same reason as 1).
3. Run the processing against a range of data rather than the whole table. (Same reason as 1).
4. Add additional rollback segments. This will allow the updates etc. to be spread across more
rollback segments thereby reducing the chances of overwriting required rollback information.
5. If fetching across commits, the code can be changed so that this is not done.
6. Ensure that the outer select does not revisit the same block at different times during the
processing. This can be achieved by:
o Using a full table scan rather than an index lookup
o Introducing a dummy sort so that we retrieve all the data, sort it and then sequentially
visit these data blocks.

Case 2 - Rollback Transaction Slot Overwritten

1. Use any of the methods outlined above except for '6'. This will allow transactions to spread their
work across multiple rollback segments therefore reducing the likelihood or rollback segment
transaction table slots being consumed.
2. If it is suspected that the block cleanout variant is the cause, then force block cleanout to occur
prior to the transaction that returns the ORA-1555. This can be achieved by issuing the following
in SQL*Plus, SQL*DBA or Server Manager :

alter session set optimizer_goal = rule;


select count(*) from table_name;

If indexes are being accessed then the problem may be an index block and clean out can be forced by
ensuring that all the index is traversed. Eg, if the index is on a numeric column with a minimum value of
25 then the following query will force cleanout of the index:

select index_column from table_name where index_column > 24;

Examples

Listed below are some PL/SQL examples that can be used to illustrate the ORA-1555 cases given above.
Before these PL/SQL examples will return this error the database must be configured as follows:

 Use a small buffer cache (db_block_buffers).


REASON: You do not want the session executing the script to be able to find old versions of the
block in the buffer cache which can be used to satisfy a block visit without requiring the rollback
information.
 Use one rollback segment other than SYSTEM.
REASON: You need to ensure that the work being done is generating rollback information that
will overwrite the rollback information required.
 Ensure that the rollback segment is small.
REASON: See the reason for using one rollback segment.

Rollback Overwritten

rem * 1555_a.sql - Example of getting ora-1555 "Snapshot too old" by


rem * a session overwriting the rollback information required
rem * by the same session.
drop table bigemp;
create table bigemp (a number, b varchar2(30), done char(1));
drop table dummy1;
create table dummy1 (a varchar2(200));
rem * Populate the example tables.
begin
for i in 1..4000 loop
insert into bigemp values (mod(i,20), to_char(i), 'N');
if mod(i,100) = 0 then
insert into dummy1 values ('ssssssssssss');
commit;
end if;
end loop;
commit;
end;
/
rem * Ensure that table is 'cleaned out'.
select count(*) from bigemp;
declare
-- Must use a predicate so that we revisit a changed block at a different
-- time.
-- If another tx is updating the table then we may not need the predicate
cursor c1 is select rowid, bigemp.* from bigemp where a < 20;
begin
for c1rec in c1 loop
update dummy1 set a = 'aaaaaaaa';
update dummy1 set a = 'bbbbbbbb';
update dummy1 set a = 'cccccccc';
update bigemp set done='Y' where c1rec.rowid = rowid;
commit;
end loop;
end;
/

Rollback Transaction Slot Overwritten

rem * 1555_b.sql - Example of getting ora-1555 "Snapshot too old" by


rem * overwriting the transaction slot in the rollback
rem * segment header. This just uses one session.
drop table bigemp;
create table bigemp (a number, b varchar2(30), done char(1));
rem * Populate demo table.
begin
for i in 1..200 loop
insert into bigemp values (mod(i,20), to_char(i), 'N');
if mod(i,100) = 0 then
commit;
end if;
end loop;
commit;
end;
/
drop table mydual;
create table mydual (a number);
insert into mydual values (1);
commit;
rem * Cleanout demo table.
select count(*) from bigemp;
declare
cursor c1 is select * from bigemp;
begin
-- The following update is required to illustrate the problem if block
-- cleanout has been done on 'bigemp'. If the cleanout (above) is commented
-- out then the update and commit statements can be commented and the
-- script will fail with ORA-1555 for the block cleanout variant.
update bigemp set b = 'aaaaa';
commit;
for c1rec in c1 loop
for i in 1..20 loop
update mydual set a=a;
commit;
end loop;
end loop;
end;
/

Special Cases

 There are other special cases that may result in an ORA-01555. These are given below but are rare and
so not discussed in this article:

 Trusted Oracle can return this if configured in OS MAC mode. Decreasing


LOG_CHECKPOINT_INTERVAL on the secondary database may overcome the problem.
 If a query visits a data block that has been changed by using the Oracle discrete transaction
facility then it will return ORA-01555.
 It is feasible that a rollback segment created with the OPTIMAL clause may cause a query to
return ORA-01555 if it has shrunk during the life of the query causing rollback segment
information required to generate consistent read versions of blocks to be lost.

Summary

This article has discussed the reasons behind the error ORA-01555 "Snapshot too old", has provided a
list of possible methods to avoid the error when it is encountered, and has provided simple PL/SQL
scripts that illustrate the cases discussed.

You might also like