ORA-01555: snapshot too old: rollback segment number %s with name "%s"
too small
PLEASE NOTE:
This article was written long, long ago (December 1997) for an
internal technical newsgroup for developers at my company. The
explanation lacks some of the technical details of how Oracle
consistent read mechanism really works within the buffer cache, so
advanced readers, be aware. The overall principle presented is,
nevertheless, valid and accurate.
*******************
Problem: You are running a query that (for whatever reason) takes a
long time to complete. One or more of the tables you are querying is
being changed by other users while you perform your query. After some
time, you receive the ORA-01555, and your query fails.
Explanation:
When you perform a query, Oracle knows the point in time (called a
system change number or SCN) at which your query began. In order to
give you a consistent set of data, Oracle needs to show you the data
the way it looked exactly when you began your query.
Meanwhile, people are changing the underlying data being selected by
your query. These other transactions are actually changing the data
on the datafiles. As a part of their transaction, they record the
data in the rollback segments the way it looked before changing, in
case they need to perform a rollback before they commit. This data
comes in handy for you, because it lingers around in the rollback
segments even after the other transactions have committed. While your
query is scanning through a datafile selecting data, it might come
upon a piece of data that is newer than the query you are performing.
At this point it goes off and checks for this data in the rollback
segments. Usually it finds it, and moves on.
The problem is that Oracle doesn't know what your long-running query
might need in the future. In a very transactional environment, the
rollback segments are changing constantly, and fairly rapidly. It is
possible that the piece of old data that you need from the rollback
segments will have already been overwritten by some other transaction
before you get to it. When your query encounters this situation, it
generates an ORA-01555 and fails.
Solutions:
1. Avoid querying rapidly changing data over a long period of time.
If you have a query that is going to run for a long time, and which
selects a long time period of data (such as a month), Try segmenting
your query into two parts: Everything but the past four days, and just
the last four days. Remember that in a query that selects a whole
month, you spend hours grinding through the fairly quiescent data from
the first part of the month, and only much later get down to the newer
stuff (which, incidentally, is changing heavily). Segmenting in this
way could very well solve your problem. This is also probably why
month end reports eventually run successfully, once the month end is a
few days past. At that point, the data for the 29th and 30th is no
longer being heavily changed.
2. Increase the number of rollback segments, in hopes that you will
get lucky and nobody will overwrite the data you are planning to
select somewhere down the road. This isn't a very good solution,
because it probably won't work on a very transactional database.
3. Maintain a read-only snapshot database instance in which certain
tables from the OLTP instance are refreshed at some interval. This
would be useful, but implementation is a little far away right now.
4. Tune the queries to complete faster, reducing the possibility that
data will change out from under the query, and eventually become
unavailable.
Copyright © 1997, Jeremiah Wilton
Reproduction prohibited without permission of the author