Escolar Documentos
Profissional Documentos
Cultura Documentos
This article( taken from Oracle website ) will discuss the circumstances under which a query can
return the
Oracle error ORA-01555 "snapshot too old (rollback segment too small)". The
article will then proceed to discuss actions that can be taken to avoid the
error and finally will provide some simple PL/SQL scripts that illustrate the
issues discussed.
Terminology
~~~~~~~~~~~
It is assumed that the reader is familiar with standard Oracle terminology such
as 'rollback segment' and 'SCN'. If not, the reader should first read the Oracle
Server Concepts manual and related Oracle documentation.
In addition to this, two key concepts are briefly covered below which help in
the understanding of ORA-01555:
1. READ CONSISTENCY:
====================
This is documented in the Oracle Server 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').
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.
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.
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.
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 :
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.
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.
Steps:
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.
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.
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,
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.
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 :
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
:
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 :
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 :
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.
REASON: You need to ensure that the work being done is generating rollback
information that will overwrite the rollback information required.
ROLLBACK OVERWRITTEN
rem * 1555_a.sql -
rem * Example of getting ora-1555 "Snapshot too old" by
rem * session overwriting the rollback information required
rem * by the same session.
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
declare
begin
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 :
o If a query visits a data block that has been changed by using the Oracle
discrete transaction facility then it will return ORA-01555.
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.