Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Dennis.

Asked: February 05, 2003 - 2:28 pm UTC

Last updated: September 29, 2010 - 1:16 pm UTC

Version: 9.2.0

Viewed 10K+ times! This question is

You Asked

Tom,

Hope all is well. Sorry I'm on IE (bleah), was having problems with Netscape, opened up IE, and here I was with the chance to ask a question! Mozilla doesn't like our authentication server, so I can't use that at work.

Anyway, to the question.
We are having exports fail with 1555 Snapshot too old errors. This has been going on randomly for a few months. I've been thinking it's our undo retention period. When we went to 9i, we had a retention of 15 minutes, but kept blowing out the UNDO tablespace. In some moment of infinite wisdom, it was decided to set the retention to ZERO (keep in mind I'm not considered a "system" dba so my input isn't as valuable). Anyway, today they decided to increase the size of the UNDO and I threw a fit about how it wasn't going to fix the problem, and we need to up the retention time (which will lead to a need to increase the UNDO tablespace, but I don't want them to keep throwing space at it in a futile attempt). I then explained delayed block cleanout to them (since they didn't know how you could get 1555 without active transactions on the tables) and sent them a link (to this very site).

Now they seem stuck on why it has to perform block cleanout with a retention time of 0. I guess I don't have a good answer for them if delayed block cleanout isn't clear enough. Isn't it that We've changed the data, cleared out the undo segments thanks to our 0 time, and now we are trying to export (we export right after a load). So, it says "hey this block is modified" and tries to reconstruct the original image, and of course fails.

What am leaving out in my explaination to them?? How does undo differ from plain old rbs in this respect?

They are saying that "according to documentation, it only overwrites the undo data if there is not enough free space". I'm always seeing the UNDO tablespace at 0% (2.88 MB out of 6GB right now). Doesn't the statement from the documentation ONLY apply if we actually had a retention time, and then it would be just like the old RBS in this respect? With a time of 0, we are shooting ourselves in the foot, or so I think.

Thanks Tom. Sorry for a repeat question (here's the link to what I sent them...

</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:360536564061,%7Bdelayed%7D%20and%20%7Bblock%7D%20and%20%7Bcleanout%7D <code>

As always,

Thanks for the help/assistance/insight/knowledge transfer/advice.

Dennis

and Tom said...

an undo tablespace is simply a tablespace where Oracle decides how many RBS's to create and how big they should grow to.

Under the covers -- it is still JUST ROLLBACK SEGMENTS -- no different. It is just that WE decide how many and how big instead of you.

If you have an undo retention period that is very small, there is nothing to motivate us to extend an rbs -- hence you have the same problem. You want to up the undo retention. Bear in mind that this parameter (retentation) is a SUGGESTION from you to us. It'll not cause us to "blow out" undo space - if you constrain us to x megabytes -- we'll stop.

See
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:6894817116500 <code>

they should feel very safe in setting undo retention to 500 hours - if they've also constrained us to a fixed amount of space they are willing to give us.


It is very very easy to test this (that we grow only when we need to).


ops$tkyte@ORA920> create undo tablespace undo_new
2 datafile size 100m
3 /
Tablespace created.

ops$tkyte@ORA920> alter system set undo_tablespace = undo_new;
System altered.

ops$tkyte@ORA920> alter system set undo_retention = 0;
System altered.

ops$tkyte@ORA920> create table t ( x char(2000) );
Table created.

ops$tkyte@ORA920> insert into t values ( 'x' );
1 row created.

ops$tkyte@ORA920> commit;
Commit complete.

ops$tkyte@ORA920> @freef 1 undo_new

%
Tablespace Name KBytes Used Free Used
---------------- ------------ ------------ ------------ ------
*UNDO_NEW 102,400 1,344 101,056 1.3
------------ ------------ ------------
sum 102,400 1,344 101,056

at the beginning of the test - we are using about 1m of UNDO in the undo tablespace. Now we generate gobs of UNDO:

ops$tkyte@ORA920> begin
2 for i in 1 .. 100000
3 loop
4 update t set x = 'x';
5 commit;
6 end loop;
7 end;
8 /

PL/SQL procedure successfully completed.

ops$tkyte@ORA920> @freef 1 undo_new

%
Tablespace Name KBytes Used Free Used
---------------- ------------ ------------ ------------ ------
*UNDO_NEW 102,400 1,344 101,056 1.3
------------ ------------ ------------
sum 102,400 1,344 101,056

and at the end -- we are using -- the same 1m. We obviously wrapped around and around. There we NOTHING to motivate us to extend the rbs's in there -- the undo retention was set low. So, we bump it up a tad:

ops$tkyte@ORA920> alter system set undo_retention = 10000;
System altered.

ops$tkyte@ORA920> begin
2 for i in 1 .. 100000
3 loop
4 update t set x = 'x';
5 commit;
6 end loop;
7 end;
8 /

PL/SQL procedure successfully completed.

ops$tkyte@ORA920> @freef 1 undo_new

%
Tablespace Name KBytes Used Free Used
---------------- ------------ ------------ ------------ ------
*UNDO_NEW 102,400 102,400 0 100.0
------------ ------------ ------------
sum 102,400 102,400 0


and look at that -- we were motivated to expand the rbs's in there -- upto 100m (and not a byte more, I didn't put autoextend on and believe me, that was more then 100meg of undo -- a char(2000) is 2000 bytes for each update)

so, yes, they need to UP the retention as well as dedicate more space, we'll fill it up and take it from there.


Rating

  (111 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Nitin sharma, February 06, 2003 - 12:42 am UTC

its always great to know whats going on behind the curtain ....great insight of undo management...

clarification

Dennis, February 06, 2003 - 8:21 am UTC

I guess I wasn't clear enough, but you got the answer to me.

My comment about blowing out the UNDO was that we didn't have enough space to allow us 15 minutes of UNDO, so we were getting unable to extend RBS errors. That was why the 'system' people dropped the retention to 0, rather than up the size of the UNDO. Now, they are wanting to keep the export from failing with snapshot too old errors by throwing space at the UNDO, but that isn't where the problem is (fully). We need to up the retention to a point in time where the export can perform delayed block cleanout without running into an overwritten (wrapped) RBS segment, and then we will be fixed. So it's a combo of adding space and upping the retention time. (On a side note, I could not enable resumable due to the below, so I dropped the retention back to zero right before I left, and our export still failed with ORA-01555 errors - even with the extra space, so that will help out the defence of the delayed block cleanout being the culprit) :)

Since nobody is here to monitor the load, I was trying to set the schema to resumable in case we didn't add enough UNDO for the retention period, but the developers load most of the tables with an insert /*+ append */ from another database, and of course resume doesn't work with distributed transactions. Do you know of a work-around for that, or is that a topic for a new thread?

Thanks Tom. You're the greatest!
Dennis

Tom Kyte
February 06, 2003 - 9:12 am UTC

...
My comment about blowing out the UNDO was that we didn't have enough space to
allow us 15 minutes of UNDO, so we were getting unable to extend RBS errors.
....

Sorry -- but the above example shows that won't happen.

UNDO_RETENTION = 10000
undo space = 100m
undo space of 100m was not NEARLY enough to hold 10,000 seconds of UNDO.

undo_retention is "advice" or "a hint", "a request". It is not a directive. it'll not blow out the rbs -- else I would have blown out with "failed to extend" myself above!


set the retention really high.
create the undo tablespace as big as they want it to be and don't autoextend the datafiles.

undo will grow to that size and not a BYTE larger.


So -- I'm a little confused here....

sorry

Dennis, February 06, 2003 - 9:37 am UTC

I was thinking that yours worked because you had frequent commits...every transaction was set to inactive...but then you still wouldn't have met the time limit so I don't know what I was thinking. I think that you used a commit in a for loop just shook me up too bad for me to focus and all I could think about was "he committed".

Sorry for the "my bad". I will disassociate the whole "must keep time" thing from my head, and assume that they got an error due to a larger load than normal, and didn't inform us of that, and then the system dbas took the retention time down and the reload worked (maybe they only loaded part of it).

This is why you should fix problems when they occur, so you have all the facts, and not just supposition.

At any rate, thanks for the extra clarification of the UNDO and the retention setting. Sorry I was confused too. I must need more caffeine or sleep, or both. But neither of those is really fun hehe.

Thanks Tom.
Dennis


Tom Kyte
February 06, 2003 - 10:14 am UTC

Yes, the failure to extend was because you really "ran out of room". It would have happened REGARDLESS of the undo retention setting!

Sleep not fun? ;)

not at all!

Dennis, February 06, 2003 - 11:58 am UTC

I see my grammar suffers as well :)

It should have been "you using a" not "you used a". I know you needed that for the example, but it was just an oddity and I got all focused in on the commit part (probably because I'm a little loopy from not sleeping) :)

Of course sleep isn't fun! All you do is lay there and have cool dreams....but you could be destroying monsters or cities online, hanging with the family/friends, playing pain(t) ball, or trying to finish JPL's book so you can finally open up the bible of Oracle before a new one gets published ;)

Those are the fun things!

Dennis

Need some help

Dennis, February 20, 2003 - 12:46 pm UTC

Tom,

Like the changes, pretty neat!!

There are a few doubts held. If you could provide clarification, then that would be wonderful. Thank you for your time and patience.

1) Does every transaction have to go to the UNDO, even if it is committed? If the SCN is higher than that on the block, why does it need to go to the UNDO?

2) How does DBWR know that the block is committed? Wouldn't it have to also suffer delayed block cleanout and risk getting a snapshot too old? It doesn't read the redo log, and if the undo has been overwritten, then wouldn't we be losing transactions??

3) The block in the buffer cache has to be marked committed, it can't just be marked change and have to refer to the undo segment, or else we would be losing transactions. Is that correct?

4) What if the next process doesn't read the changed block (dirty block) for a long time?

5) We are only having problems with the export. Again, the feeling here is that it is not understood why the UNDO (RBS)must be visited. No changes are happening to the database when the export starts or during the export, and a change of exporting with consistent=n (we were using y previously) caused the error to disappear. Why? We did not mess with UNDO retention yet(it is still 0).

6) If we forced a log switch before the export, and then went back to consistent=y, would we be able to export without errors again?

Thanks Tom. Sorry it's a long one. (don't a few short ones make up?)
Dennis

Tom Kyte
February 20, 2003 - 7:02 pm UTC

1) reads goto undo if and when they need to. modifications, well they GENERATE undo so they pretty much always go there (with special exceptions like INSERT /*+ APPEND */)

2) it doesn't. DBWR doesn't care about read consistency, it's job is to keep the buffer clean, flush modified blocks. DBWR flushes modified blocks that have uncommitted changes all of the time.

I don't see where you are going with that particular thought...

3) why? you can have many transactions all modifying the same block at the same time. It is really quite complex. When you commit -- we do not revisit all of your blocks -- especially if they were flushed to disk already.

If you have my book "Expert One On One Oracle" -- I cover what happens to blocks during a modification and the dance that the data block, undo block and redo generated do around eachother to make this all work. It takes more room then I can here and needs a picture or two (and my ascii art just ain't up to it)

4) what if? Good question -- what if? Nothing -- same thing that happens if they read it straight away. The database doesn't care about time, it is just software - 5 milliseconds, 5 days -- it is all the same to it. the processing would be the same.

5&6) see
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:895410916429 <code>

there I get an ora1555 reading from a READ ONLY tablespace. You must have other transactions going on in there and your RBS is just sized too small for the work you are performing.. Increase the permanently allocated size of your RBS so as to make it such that it does NOT wrap around during the time it takes for you to do your export.

Switching a logfile -- which doesn't do a thing to UNDO, it is all about redo -- will have zero effect. In fact, it is so far off of the mark -- hmmm. I hate to sound like I'm trying to sell my book -- but I do think I cover this 1555 thing, how transactions work and such in pretty good detail with examples in it.



Sorry it's been awhile

Dennis, March 10, 2003 - 2:45 pm UTC

Tom,

Sorry it's been awhile on this. Had to get group consensus on the list of questions for you. Here goes.

1)
Sorry this was not more clear. Why would a read transaction have to visit the undo block if the SCN of the read transaction start time is higher than the SCN
of the block?

2)
We didn't realize that DBWR flushed uncommitted transactions to disk. The thought we were trying to present was that if the block is not marked as
transaction committed, and the only place it is recorded is the REDO and UNDO, then commits to the block would be lost because the UNDO is overwritten and there is no record of the block
being changed (other than in the redo log).

3)
So when a block is read that is in the buffer (it's dirty), and the UNDO is already overwritten, is it assumed that the changes to it are committed and the block is valid?

4)
Sounds good.

5)
We are assured that nothing is going on at the time of the export. Other than sitting here one night and watching top_sessions, any other recommendations on
how to tell that something is going on?

6)
Sorry, yes a log switch is redo, but it also forces a checkpoint, which flushes the buffer to disk. This seems to have caused the error to go away
(we changed back to CONSISTENT=Y and do a log switch before the export (CONSISTENT=N also let us export without errors), and still have left the
UNDO_RETENTION at 0. We have run for a week and a half with no errors. Does this help spark any idea of what could be going on?

Thanks Tom for your help. We have your book, but feel that the above questions are left open.

As always,
Thank you for your time and patience.

Dennis

Tom Kyte
March 10, 2003 - 6:14 pm UTC

1) here is a short excerpt from my book "Expert one on one Oracle" from chapter 5:

Delayed Block Cleanout

This cause of the ORA-01555 is harder to eliminate entirely but is rare, as the circumstances under which it occurs do not happen frequently (at least not in Oracle8I anymore). We have already discussed the block cleanout mechanism, but to summarize, it is the process whereby the next session to access a block after it has been modified may have to check to see if the transaction that last modified the block is still active. Once it determines that it is not active, it cleans out the block so that the next session to access it does not have to go through that process again. In order to clean out the block, 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. This confirmation is accomplished in one of two ways. One way is that Oracle can determine that the transaction committed a long time ago, even though its transaction slot has been overwritten in the rollback segment transaction table. The other way is that the commit SCN is still in the transaction table of the rollback segment, meaning the transaction committed a short period of time ago and its transaction slot hasn't been overwritten.

In order to receive the ORA-01555 from a delayed block cleanout, all of the following conditions must be met:

? A modification is made and commits and the blocks are not cleaned out automatically (for example, it modified more blocks then fit in 10% of the SGA block buffer cache).
? Those blocks are not touched by another session and will not be touched until our unfortunate query below hits it.
? A 'long running' query begins. This query will ultimately read some of those blocks from above. This query starts at SCN 't1'. That is the read consistent SCN it must roll data back to in order to achieve read consistency. The transaction entry for the modification transaction is still in the rollback segment transaction table when we began.
? During the query, many commits are made in the system. These transactions do not touch the blocks in question (if they did we wouldn't have the impending problem).
? The transaction tables in the rollback segments roll around and reuse slots due to the high degree of commits. Most importantly, the transaction entry for the original modification transaction is cycled over and reused. In addition, the system has reused rollback segment extents, so as to prevent a consistent read on the rollback segment header block itself.
? Additionally, the lowest SCN recorded in the rollback segment now exceeds 't1' (it is higher than the read consistent SCN of the query) due to the large amount of commits.

Now, when our query gets to the block that was modified and committed before it began, it is in trouble. Normally, it would go to the rollback segment pointed to by the block and find the status of the transaction that modified it (find the commit SCN of that transaction). If the commit SCN is less then 't1', our query can use that block. If the commit SCN is greater then 't1' our query must rollback that block. The problem is however that our query is unable to determine in this particular case if the commit SCN of the block is greater then or less then 't1'. It is unsure as to whether it can use it or not. The ORA-01555 then results.
......

3) nope -- not at all. It (read consistency) has nothing to do with whether the changes are committed or not. It has to do with "what did the block look like when my statement began". If someone modifies a block and commits it whilst we are reading the table, we'll still see the image of the block from BEFORE the modification.

5) watch the system, probably deferred block cleanout. but then again the problem statement is very vague above "we are having a problem"

6) it fires a log switch checkpoint, which will eventually, sometime, lazily (maybe hours later) cause the block to be flushed to disk.

Go back to the way you did it before, you'll get the same response from the system. It was a fluke most likely caused by the delayed block cleanout.




Script content?

Fenng, March 11, 2003 - 4:14 am UTC

Hi,Tom ,
Could you show me the contents of **freef** script?

Thank you very much!


Tom Kyte
March 11, 2003 - 7:59 am UTC

--------------------------------------------------------
-- free.sql
--
-- This SQL Plus script lists freespace by tablespace
--------------------------------------------------------

column dummy noprint
column pct_used format 999.9 heading "%|Used"
column name format a16 heading "Tablespace Name"
column Kbytes format 999,999,999 heading "KBytes"
column used format 999,999,999 heading "Used"
column free format 999,999,999 heading "Free"
column largest format 999,999,999 heading "Largest"
column max_size format 999,999,999 heading "MaxPoss|Kbytes"
column pct_max_used format 999.9 heading "%|Max|Used"
break on report
compute sum of kbytes on report
compute sum of free on report
compute sum of used on report
select name, kbytes, used, free, pct_used
from (
select (select decode(extent_management,'LOCAL','*','') from dba_tablespaces where tablespace_name =
b.tablespace_name) || nvl(b.tablespace_name,
nvl(a.tablespace_name,'UNKOWN')) name,
kbytes_alloc kbytes,
kbytes_alloc-nvl(kbytes_free,0) used,
nvl(kbytes_free,0) free,
((kbytes_alloc-nvl(kbytes_free,0))/
kbytes_alloc)*100 pct_used,
nvl(largest,0) largest,
nvl(kbytes_max,kbytes_alloc) Max_Size,
decode( kbytes_max, 0, 0, (kbytes_alloc/kbytes_max)*100) pct_max_used
from ( select sum(bytes)/1024 Kbytes_free,
max(bytes)/1024 largest,
tablespace_name
from sys.dba_free_space
group by tablespace_name ) a,
( select sum(bytes)/1024 Kbytes_alloc,
sum(maxbytes)/1024 Kbytes_max,
tablespace_name
from sys.dba_data_files
group by tablespace_name
union all
select sum(bytes)/1024 Kbytes_alloc,
sum(maxbytes)/1024 Kbytes_max,
tablespace_name
from sys.dba_temp_files
group by tablespace_name )b
where a.tablespace_name (+) = b.tablespace_name
)
where name like upper('%&2%')
order by &1
/


Really helped! But a couple of clarifications needed for me...

steve, April 15, 2003 - 7:17 am UTC

Hi Tom,

We are using Oracle 9iR2 on Solaris. We are using the UNDO
tablespace feature (i.e. not manual RBS). Our UNDO
tablespace is 4 Gigs. We were experiencing
SNAPSHOT TOO OLD errors and increased the undo retention
from 900 seconds to 5 hrs (thanks to this thread!!). That
solved the errors we were having. Thanks!


I just ran a huge delete statement whci took over 20 minutes.
I believe it was running on _SYSSMU1$. The delete was
immediately followed by a commit.

We then ran a second delete which failed almost immediately
("UNABLE TO EXTEND UNDO TABLESPACE"). The query was running on
_SYSSMU4$ (I think). Here is what the rollback segments look
like just before the second delete failed:


OPT
NAME SIZ EXTENT RSSIZE aveactive EXTENDS SHRINKS WRAPS # trans HWMSIZE
---------- ---- ------ ------- --------- ------- ------- ----- ------- -------
SYSTEM 7 .42 .00 0 0 0 0 .42
_SYSSMU1$ 133 1488.17 852.72 505 79 918 0 1536.11
_SYSSMU2$ 127 1340.11 665.74 551 85 970 0 1408.11
_SYSSMU3$ 30 58.17 101.35 380 74 742 0 312.11
_SYSSMU4$ 74 209.17 353.09 464 80 866 1 472.11
_SYSSMU5$ 4 2.11 114.38 426 81 791 0 344.11
_SYSSMU6$ 4 .23 43.68 487 83 899 0 256.11
_SYSSMU7$ 21 2.23 .14 426 74 810 0 352.11
_SYSSMU8$ 46 154.17 129.25 616 107 993 0 296.11
_SYSSMU9$ 27 192.17 184.77 421 77 797 0 417.11
_SYSSMU10$ 156 519.17 475.76 607 82 1125 0 559.17

11 rows selected.


My questions are the following.

1. When does the RSSIZE go down and by what process?

2. When you say:

undo_retention is "advice" or "a hint", "a request". It is
not a directive. it'll not blow out the rbs -- else I would
have blown out with "failed to extend" myself above!

That applies only to the current RBs - right? What I mean is:

Our query failed almost immediately. Had we been on _SYSSMU1$,
it would have had a better chance of succeeding - right? It would
have overwritten extents that were "younger" than the UNDO_RETENTION,
allowing the delete to proceed. This overwritting of extents that
are yonger than the UNDO_RETENTION applies only to the current RBS.
It's not as though extents from another RBS can be released to the
tablepsace, allowing other RBSs to grow when needed.

I guess it failed quickly because we were on a relatively small RBS
and there was no place left to grow (without "stealing" from the
other RBSs).

Am I understanding correctly?

3. So if my understanding is correct, a high UNDO_RETENTION can increase
the likelihood of "Unable to Extend Tablespace UNDO..." errors - right?


Thank you very very much Tom.

Steve

Tom Kyte
April 15, 2003 - 8:37 am UTC

1) internal, undocumented, and changing. What this means in your case is that you have a need for more undo space in your database given the work load you are throwing at it.

2) here undo_retention had nothing to do with it. The issue was the RBS you were assigned to could not grow to accomodate the work you needed to perform. It mattered not if undo_retention was 1 second or 5 days -- your transaction had a need to generate gobs of UNDO and was unable to since you limited the rbs to 4gig.

If you had been assigned to the "larger" allocated rbs, it would have run longer and if there had been sufficient space.

3) No, yes, sort of, indirectly, not really. (false causality happening here)

Unable to extend happens because you run out of space. Period.

If you set a high undo retention -- you are asking us to use more space.

If you ask us to use more space then you give us, we'll be unable to extend.

(a circular argument...)

OLTP x DSS

David, April 15, 2003 - 9:32 am UTC

Tom, as a guideline I have learned -- as far as old RBS's go:

OLTP:
. more rbs's
. small rbs's
. concurrent ativity
. "round-robin" allocation fashion ( I also heard I could be "next least used" -- which one is true ? )
. no. of rbs's = aprox. no. of transactions / 4

DSS:
. few or one rbs
. large
. small or no concurrent activity
. size of rollback difined by largest long-running transaction

In a mixed environment with OLTP and DSS, both types of rbs live together. For example, we can have many small rbs's for oltp and a large one for dss and use them either:
. assigning them by offlining the dss rbs and onlining the oltp rbs's during the day and vice-versa for the night (supposing they work alone in those periods of the day)
. explicitly assigning oltp and dss apps with USE ROLLBACK SEGMENT

That was the "rule of thumb" -- I know you're not fond of ROT's... ;)

How would you distribute a mixed OLTP x DSS workload in the same database with the new undo management ?

Thanks !

Tom Kyte
April 15, 2003 - 10:09 am UTC

let them all grow as big as they need to be. (hate use rollback segment)

For DSS why do you need big rbs's?

Maybe for DW -- but even then, most ETL operations should be done in a mode that generates little to no undo/redo.

Followup/results

Steve, April 15, 2003 - 10:17 am UTC

Thanks!

FYI:  Might be helpful for other readers...

Since we last "spoke", we have been doing massive deletes from 3
tables. But instead of doing it day by day, we have been doing 
hour by hour with commits after each hour. We have never
received "Unable to extend Tablespace" errors which
makes sense. Also, each RBS looks "more or less" the same size
(also makes sense).

     
           OPT     EXT          ave   ave
 NAME       IZE ENTS RSSIZE activ shrink EXTENDS SHRINKS WRAPS #trans HWMSIZE
 ---------- --- ---- ------ ----- ------ ------- ------- ----- ------ -------
 SYSTEM            7    .42   .00    .00       0       0     0      0     .42
 _SYSSMU1$        56 477.30 16.89  26.14     558      98  1105      0 1536.11
 _SYSSMU2$        27 215.42 12.47  25.18     579     106  1170      1 1408.11
 _SYSSMU3$        56 393.36 18.74  14.64     560      94  1142      1  393.36
 _SYSSMU4$        44 281.48 18.17  17.94     535      97  1197      0  472.11
 _SYSSMU5$        53 265.48 17.07  15.61     579     101  1234      0  344.11
 _SYSSMU6$        70 486.23 19.78  15.21     714     107  1358      0  487.98
 _SYSSMU7$        96 654.30 29.37  16.97     645      96  1249      0  654.30
 _SYSSMU8$        53 380.30 24.40  19.16     740     123  1331      1  466.23
 _SYSSMU9$        68 483.36 21.24  18.93     489      84  1113      0  483.36
 _SYSSMU10$       52 349.36 21.25  17.64     655     105  1364      0  559.17
 
 
But now our UNDO_RETENTION is "shot". Again, makes sense.


SQL> select count(*) from mo as of 
     timestamp sysdate-(2/24)
                      *
ERROR at line 1:
ORA-01555: snapshot too old: rollback segment number 5 with name "_SYSSMU5$"
too small




SQL> SHOW PARAMETER

    undo_retention                       integer     18000


    
    
It's making much more sense. Thanks a lot Tom.

How much ($$) to get the "internal, undocumented" info?  ;)


I appreciate all your help.

Steve
 

undo retention time for OLTP - - 9.2.0.3

Baqir Hussain, May 23, 2003 - 3:23 pm UTC

Tom,
I have two questions:

1. What should be the undo retention time for an OLTP system?

2. If we use default undo retention time (10800) for an OLTP system - what will be the pro and cons? Are we seeing any performance problem by setting it up to 10800?

Tom Kyte
May 24, 2003 - 9:55 am UTC

I have questions for your questions

how long do you need it for? You would want undo to be retained for at least as long as your longest running query. If you have any "flashback" requirements, they would have to be considered as well.

You would like your undo to be as small as possible -- but -- as big as it needs be. Too small -- ora-1555 snapshot too old. Too large -- can be a performance issue.

So, figure out your long running query times and start with that.

A reader, May 25, 2003 - 11:06 am UTC

Hi Tom,
We will migrate to oracle 9i in near feature and we are
planning to use UNDO tablespace.

Here is the problem...

In many batch jobs and stored procedure our develpoer use
statement
SET TRANSACTION USE rollback segment = XXXX

Do we have to modofy all batches and stored procedures?

I've seen one init.ora parameter undo_suppress_errors.

Can this parameter setting help anyway in our case if we
don't modify our programs?

Thanks




Tom Kyte
May 25, 2003 - 11:36 am UTC

that parameter will make it so that the "set transaction" statement will silently "fail". It will appear to have worked but won't really do anything.

yes, it can be used to "fix" this issue.

A reader, May 25, 2003 - 11:53 am UTC

Hi Tom,

I ran quick test on this but it doen't seems to working

SQL>  ALTER SYSTEM SET undo_suppress_errors  = TRUE SCOPE = BOTH;

System altered.

SQL> SHO PARAMETER SUPPRESS

NAME                                 TYPE                  VALUE
------------------------------------ --------------------- --------------------
undo_suppress_errors                 boolean               TRUE
SQL> CREATE OR REPLACE PROCEDURE  TEST_UNDO IS
  2  begin
  3  execute immediate 'SET TRANSACTION USE rollback segment = RB01';
  4  end;
  5  /

Procedure created.

SQL> EXEC TEST_UNDO ;
BEGIN TEST_UNDO ; END;

*
ERROR at line 1:
ORA-02245: invalid ROLLBACK SEGMENT name
ORA-06512: at "GAURANG.TEST_UNDO", line 3
ORA-06512: at line 1


It is not suppressing the error.

Any comments

Thanks 

Tom Kyte
May 25, 2003 - 12:00 pm UTC

well, you do have to use VALID syntax:

ops$tkyte@ORA920> set transaction use rollback segment rb01;

Transaction set.

ops$tkyte@ORA920> set transaction use rollback segment=rb01;
set transaction use rollback segment=rb01
                                    *
ERROR at line 1:
ORA-02245: invalid ROLLBACK SEGMENT name



lose the "=" 

should undo_suppress_errors be set to TRUE always...

Kamal Kishore, May 26, 2003 - 12:52 am UTC

Hi Tom,
Nice discussion on UNDO. clarified a lot for me.
The doubt that I have is on the optimal setting of the parameter undo_suppress_errors?
The default setting for this seems to be FALSE, thus, generating errors like :

SQL> begin
  2    set transaction use rollback segment rbs ;
  3  end ;
  4  /
begin
*
ERROR at line 1:
ORA-30019: Illegal rollback Segment operation in Automatic Undo mode
ORA-06512: at line 2


SQL>


Should this parameter be left at FALSE, and code modified to remove the SET TRANSACTION statements (may be at several places in several packages) or can it be set to TRUE permanently? Are there any issues that we should be aware of when setting it to TRUE?
Is this parameter provided as a "hot-fix" for old legacy code and recommended setting should preferably be FALSE?
Thanks,
 

Tom Kyte
May 26, 2003 - 9:29 am UTC

Here is my take on it.

o You are doing an upgrade.
o You are testing all of your code (you do that right?)
o Some of it will have to change -- that is the time to nuke the "use rollback segment" code
o you therefore should not need this (unless you haven't tested your code in the first place)


So, I guess if you don't test your stuff, this is useful as a bandaid on the morning after you upgrade -- while you are running around fixing dozens of other issues.

If you do test your stuff, you'll find and fix it before you get to the morning after the upgrade (and hence won't need it)

I would be looking for this to be false in the long run.

A reader, May 26, 2003 - 6:28 am UTC


undo retention increases does help -- 9.2.0.3

Baqir Hussain, May 29, 2003 - 12:24 pm UTC

Tom,
We are running the following:
UPDATE client_activity_by_agent_1 caba SET num_phone_contacts =
(SELECT count(DISTINCT(c.client_id)) FROM client c, journal j
WHERE c.client_id = j.client_id
AND j.is_phone_contact = 1
AND j.create_date > SYSDATE - '1'
AND caba.personnel_id = c.agent_id);
and got java.sql.SQLException: ORA-01555: snapshot too old: rollback segment number 1 with name "_SYSSMU1$" too small.

The update went through with undo_retention = 400 last week without generating this error ora-1555.

Last night I increased undo_retention = 3600 and put undotbs1 tablespace into autoextend mode and this tablespace can extend to 35G. The tablespace (undotbs1.dbf data file) did not extend at all and we got this error ora-1555.

TABLESPACE_NAME AUT BYTES
------------------------------ --- ----------

/mpmd10/bwalk01/undotbs02.dbf
UNDOTBS1 YES 1048576000

/mpmd10/bwalk01/undotbs01.dbf
UNDOTBS1 YES 366477312



We run update job at night when there are almost no load on the database with very few users.
The undo retention time was increased to 3600 , the oracle must use/generate more rbs to accomadate it since there are enough space available in the undotbs1 tablespace in autoextend mode.
1. How can we solve this problem?
2. Is it possible that autoextend feature does work for undotbs1 tablespace? May be some kind og bug??
Please advise.
Thanks

Tom Kyte
May 29, 2003 - 1:53 pm UTC

what is the max size of the datafiles however.....

what version...

what I would be tempted to do to avoid that little painful correlated subquery might be:

create global temporary table gtt ( agent_id int primary key, cnt int )
on commit delete rows;

and at runtime

insert into gtt
select agent_id, count(DISTINCT(c.client_id))
FROM client c, journal j
WHERE c.client_id = j.client_id
AND j.is_phone_contact = 1
AND j.create_date > SYSDATE - '1'
group by agent_id;

update ( select num_phone_contacts, cnt
from client_activity_by_agent_1, gtt
where client_activity_by_agent_1.agent_id = gtt.agent_id )
set num_phone_contacts = cnt;


ora-01555 in Automatic Undo mode

A Reader, July 15, 2003 - 11:24 am UTC

Hi Tom,
Can you please explain a little bit more about the ora-01555 in Automatic Undo mode. Why and how to correct it? In our case it happend when running a batch job. I checked the undo space and found it has a lot space left when (may be after) the 1555 error. The old trick does not work in 9i anymore. What should we do?
Thank you for your help.

Tom Kyte
July 15, 2003 - 11:50 am UTC

it happens for the same exact reasons it would happen in manual undo mode. you have insufficient space configured -- i don't know what "trick" you allude to.


You should ensure

a) your undoretention_period is set sufficient high (longer then your longest running queries)

b) your undo is not prematurely expired

see
</code> https://asktom.oracle.com/Misc/oramag/on-measuring-distance-and-aging.html <code>
"undo retention"

for some details

The old "trick"

A Reader, July 15, 2003 - 12:11 pm UTC

Here is the "old trick". When I try to create a large rollback segment using:
CREATE ROLLBACK SEGMENT "RB_LG"
TABLESPACE "ASI_UNDO_01"
STORAGE ( INITIAL 1024K NEXT 1024K OPTIMAL 2048K MINEXTENTS 2;

I get the following error message:
ORA-30019: Illegal rollback Segment operation in Automatic Undo mode

When I try to assign a transaction a specific rollback segment by using:
SET TRANSACTION USE ROLLBACK SEGMENT rb_lg;
I get the same error.

Thank again you for your help.

Tom Kyte
July 15, 2003 - 1:19 pm UTC

that will NOT fix an ora-1555

that will CREATE an ora-1555

the odds of an ora-1555 are 100% related to the SIZE OF YOUR SMALLEST rollback segment, never your largest.

using automatic undo, the rollback segments will grow till either

a) you run out of space

so, you don't need to have that "big one", it'll grow..

(i hated that "trick" btw)

Does free_space imply anything useful?

A reader, October 06, 2003 - 10:12 am UTC

Tom - does the free space stat on the UNDOTBS1 really imply anything? A user is saying "We're not doing anything but it is full.. what is going on .. I'm having issues". Hasn't specified what issue yet but I'm just curious. It's this just old retained information that should be ready for a flush if new stuff comes around?

Tom Kyte
October 06, 2003 - 10:35 am UTC

it is supposed to be "full"

it just means we've allocated extents in the tablespace.


It is like "temp". at the tablespace level "temp" should appear "full" -- because the space is allocated and in use by temp. It does not mean there is not any space in temp -- just that temp is allocated.



Another approach

A reader, October 06, 2003 - 12:32 pm UTC

That's what I figured..
what do you think of this approach?
select s.username, t.xidusn, t.ubafil,
t.ubablk, t.used_ublk
from v$session s, v$transaction t
where s.saddr = t.ses_addr

Accurate?

Tom Kyte
October 06, 2003 - 1:49 pm UTC

do this.

update emp set ename = ename;



and now walk away for 2 days. don't commit.


You'll be using a teeny tiny bit of UNDO as reported by that query.

BUT, you'll have prevented UNDO from rolling back around and reusing the space. Say the UNDO segment you got assigned was 5 meg in size. You would show as using a handful of blocks at best -- but the entire 5 meg of UNDO would be "unusuable" until you commit since we use it in a circular fashion -- all of the transactions that happened after you used up the 5 meg, committed -- but we cannot reuse it as yet!

Can deletes also cause 1555

Scott Watson, October 16, 2003 - 9:32 am UTC

Tom,

This morning I came across the following in my alert log

ORA-01555 caused by SQL statement below (Query Duration=4943 sec, SCN: 0x0000.4ca5643a):
Thu Oct 16 06:41:54 2003
delete from match_data where category =:"SYS_B_0"
Thu Oct 16 06:42:32 2003

Does this mean my delete suffered from a snapshot too old error. I wouldn't have thought this is possible with what I thought I understood about Oracle. I thought the delete would retrieve blocks in current mode and therefore not be subjected to 1555. Can you set me straight please?

Thanks.


Tom Kyte
October 16, 2003 - 10:49 am UTC



The delete runs the "search" part in consistent read mode.

It performs the delete in current mode.

If you tkprof a statement like that -- you'll see both query and current mode gets.

updates -- same thing, they search consistently, modify in current mode

You might be interested in the article entitled

"write consistency"

search for that on this site, could be very illuminating.

size of undo segment

A reader, January 29, 2004 - 1:24 pm UTC

Tom, great info. I read lot of articles on this site on undo management.

9.2.0.2 on Tru64.

I am getting ORA-1555 error on an undo tablespace 8GB in size. Without checking if the undo tablespace really ran out of space, I increased it to 16GB. I got the snapshot error again. I observed that it did not reach the space limit at all. It made me wonder if it got to do anything with the size of the undo segment. But, with Auto undo management, the segment size limit is determinded by the available space in the tablespace. right ?
Then I realised that our undo_retention was set to 0, a value recommended by an oracle consultant, who thinks this should be set higher ONLY when using "flashback queries".
At this point, I raised the undo_retention to 3 hours. the problem went away. Did not get the 1555.
So, I want to make sure I understand this concept right :

1. the transaction did not run out of space either in tablespace or the undo segment size
2. the transaction slot entry was overwritten. A transaction made an entry in the transaction slot and eventually was commited, and the next transaction "B" saw that the transaction "A" has expired(since undo_retention is not set) and tried to reuse the segment by overwriting the transaction header. A third query "C" tried to get the values which transaction "A" was accessing before being overwritten and got the "snashot" error.



Tom Kyte
January 29, 2004 - 1:43 pm UTC

you did not set the undo retention period to a value that exceeds the length of time your longest running query runs for.


1) correct

2) cannot say - but basically in very simple terms "since you requested undo to be kept only for 0 seconds, we kept it for that long and felt free to overwrite it as soon as we wanted to and we did"

thank you

A reader, January 29, 2004 - 3:59 pm UTC

so, is it possible in this case that even before processing all the rows(before returning the first row), the transaction header was overwritten by another transaction ?

Tom Kyte
January 30, 2004 - 7:50 am UTC

it is possible that the information needed by some query is overwritten in the undo tablespace -- yes. that is what has happened in fact with the ora1555

whats the right value

A reader, January 29, 2004 - 5:13 pm UTC

Tom, please correct me if I am wrong in my understanding of undo_retention :
I should be setting undo_retention to a value equal to the longest running query. Let say, if a transaction runs for 6 hours, I should be setting the undo_retention=6hours ?

Thanks as always for your godly advice.

Tom Kyte
January 30, 2004 - 8:03 am UTC

(query != transaction).

if you use serializable or read only isolation -- you set undo retention = a little longer than your longest running transaction.

if you use only read committed -- you set undo retention = a little longer than your longest running STATEMENT (insert/update/delete/merge or select)

my bad

A reader, January 30, 2004 - 6:53 pm UTC

Sorry about that Tom. Yes, Query != Transaction.
I meant transaction there, not query.

In serializable isolation, why would you set it LITTLE LONGER than the longest transaction ? Can you share an example. Greatly appreciate it !!!


Tom Kyte
January 30, 2004 - 8:14 pm UTC

in serializable -- you are read consistent with regards to the BEGINNING of the transaction -- not the beginning of each statement -- so, if you started a transaction at noon and ran 5000 queries in it and finished at 12:05 -- all 5,000 would be "as of noon"

in read committed, you would have 5,000 "as of" points instead of just one.

nice

A reader, January 30, 2004 - 9:24 pm UTC

Thank You !! Thank You !! Thank You !!

Undo Behaviour

Js, March 15, 2004 - 4:04 am UTC

Hi,

       Using RedHat 8.0 ORACLE 9.2.0
       ------------------------------

Sir,  In this test database undo_retention is already 0
and undo tablespace size = 1M and I am genrating 750 kb Redo
but Undo Tablespace is Still Increasing.



SQL> show parameter undo

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
undo_management                      string      AUTO
undo_retention                       integer     0      <<-----
undo_suppress_errors                 boolean     FALSE
undo_tablespace                      string      UNDO

SQL>
SQL> create undo tablespace undo2 datafile '/tmp/undo2.dbf' size 1M
  2  reuse;

Tablespace created.

SQL> alter system set undo_tablespace=undo2;

System altered.

SQL> conn rnd
Enter password:
Connected.
SQL>
QL> Create table a as select * from all_objects;

Table created.

SQL> update a set object_name=object_name;
update a set object_name=object_name
       *
ERROR at line 1:
ORA-30036: unable to extend segment by 32 in undo tablespace 'UNDO2'

             
SQL> ho ls -lh /tmp/undo2.dbf
-rw-r-----    1 oracle   oinstall     1.0M Mar 14 11:31 /tmp/undo2.dbf


     #### Size  of undo tablespace is already 1 MB ####


SQL> conn / as sysdba
Connected.
SQL> alter database datafile '/tmp/undo2.dbf' autoextend on ;

Database altered.

SQL> conn rnd
Enter password:
Connected.
SQL> set autot on stat
SQL> set autocommit on
SQL>
SQL> update a set object_name=object_name;

2803 rows updated.

Commit complete.

Statistics
----------------------------------------------------------
         33  recursive calls
       3159  db block gets
        164  consistent gets
         62  physical reads
     768860  redo size        <<----- 750 KB
     ........

SQL> ho ls -lh /tmp/undo.dbf
-rw-r-----    1 oracle   oinstall     1.3M Mar 14 11:33 /tmp/undo2.dbf

   #### Genrating 750 Kb Redo
   #### Undo Retention is 0
   #### Undo tablespace size 1m
   #### Undo Tablespace is still increasing 

SQL> /

2803 rows updated.

Commit complete.

Statistics
----------------------------------------------------------
         25  recursive calls
       3147  db block gets
        161  consistent gets
          0  physical reads
     774420  redo size
        .........

SQL> ho ls -lh /tmp/undo2.dbf
-rw-r-----    1 oracle   oinstall     1.4M Mar 14 11:33 /tmp/undo2.dbf

             ### Size 1.4 mb ####

SQL> /

2803 rows updated.

Commit complete.

Statistics
----------------------------------------------------------
         25  recursive calls
       3149  db block gets
        161  consistent gets
          0  physical reads
     778036  redo size

SQL> ho ls -lh /tmp/undo2.dbf
-rw-r-----    1 oracle   oinstall     1.6M Mar 14 11:33 /tmp/undo2.dbf

           ####  Size 1.6 Mb ####

Could you pls. explain ..


Thanks
Js


 

Tom Kyte
March 15, 2004 - 7:28 am UTC

redo <> undo


undo is UNDO
redo is REDO

they are totally different. redo is stored in the logs, undo is stored in the undo tablespace.

you have many undo segments in that teeny teeny tiny datafile. They are used in a round robin fashion. They start really really small. As you cycle through them, they are extending to hold your transactions data. Keep cycling and you'll see them hit a steady state size (assuming a single user system)

but -- i don't see the point as 1.x meg of undo tablespace isn't going to be realistic for anything.

Undo Retention Not working with me

Vipin, March 24, 2004 - 7:18 am UTC

Hi Tom,

I am the only user connected in database.

9i on Sun os

** create table t as select rownum r from dict where rownum < 25;

Table created.

**
**
**
**
** Select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER
------------------------
538552

** show parameter undo_Re

NAME TYPE VALUE
------------------------------------ ------- ------------------------------
undo_retention integer 10800
** delete from t;

24 rows deleted.

** commit;

Commit complete.

** select * from t;

no rows selected

** exec dbms_flashback.enable_at_system_change_number(538552);

PL/SQL procedure successfully completed.

** select * from t;
select * from t
*
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed


** show parameter undo

NAME TYPE VALUE
------------------------------------ ------- ------------------------------
undo_management string AUTO
undo_retention integer 10800
undo_suppress_errors boolean FALSE
undo_tablespace string UNDOTBS1
** select name,bytes from v$datafile;

NAME BYTES
------------------------------ ----------
/data8/oracle/oradata/dvlp/sys 419430400
tem01.dbf

/data8/oracle/oradata/dvlp/und 251658240 <<-----
otbs01.dbf

/data8/oracle/oradata/dvlp/drs 20971520
ys01.dbf

/data8/oracle/oradata/dvlp/ind 26214400
x01.dbf

/data8/oracle/oradata/dvlp/too 96337920
ls01.dbf

/data8/oracle/oradata/dvlp/use 26214400
rs01.dbf

/data8/oracle/oradata/dvlp/xdb 39976960
01.dbf


7 rows selected.


Thanks
Vipin

Tom Kyte
March 24, 2004 - 9:07 am UTC

you have to wait a couple of minutes to flashback -- like about 5 minutes.




Undo Retention Control

Vivek Sharma, May 18, 2004 - 12:00 pm UTC

Dear Tom,

Last paragraph in Chapter 2 of Oracle Documentation under heading "Undo Retention Control" states that

"In general, it is a good idea not to set retention to a value very close to hat the undo tablespace can support, because that may result in excessive movement of space beteen undo segments. A 20% buffer of undo space is recommended."

I am unable to understand what it meant. Can you please explain me for my better understanding.

Thanks and Regards
Vivek


Tom Kyte
May 18, 2004 - 6:23 pm UTC

</code> http://docs.oracle.com/docs/cd/B10501_01/server.920/a96524/c03block.htm#16044 <code>

you know, i'm not really sure what they meant by that at all. 'Movement of space between undo segments' isn't computing with me.

You might file a doc tar on that one, not sure it really makes any sense.

Reply from Oracle against TAR on Explanation of Paragraph

Vivek Sharma, May 20, 2004 - 9:53 am UTC

Dear Tom,

I had logged an Itar for the explanation of a paragraph under the heading Undo Retention Control of Chapter 2 (Oracle Documentation).

The Support Executive replied
"If the retention is set high for example or there's too less space left (or both) then undo is needed and wil be de-allocated from existing undo segments (for example rollbacksegment r01) and will be allocated to the rollbacksegment that needs it ( for example rollback segement SMU10) ."

Is this statement true. According to the explanation provided by them I could understand that
"I start my transaction which is automatically assigned to segment undo1. If the retention is set too high and there is no space left, then according to your explanation, it will move the space from another segment thus causing
performance degradation."

Please give your opinion.

Regards
Vivek



Tom Kyte
May 20, 2004 - 11:53 am UTC

it will not "move space", it doesn't work that way.

Checkpoint, undo_retention, and log_checkpoint_timeout

Mark Umbach, June 08, 2004 - 1:56 pm UTC

Much of the information provided verified my current knowledge. We just recently upgraded from 8.1.7.4 to 9.2.0.4. Here is the situation:

An ETL job loads a table using DML. It is a design issue and should not be done that way but too late in the game . . .

A subsequent job reads that table and utilizes direct-path load to load another table.

Several of these are happening at the same time.

ORA-01555 was a way of life in the Loader job.

The avenue selected was to try to write the dirty blocks on a frequent basis.

While in 8.1.7.4 this was negotiated by Increasing rollback space, segments, and commit levels, and setting log_checkpoint_timeout to an amount where the rollback would easily fit into the tablespace. The 'several processes' were run serially so as not to interfere with each other - the fear being the non-guaranteed use/retention of RBS (round-robin). This was tuned so there were no longer any ORA-01555's.

When moving the 9.2.0.4 life was going to get better as UNDO was sized (7.5G) to easily hold 'all' processes' undo for 200 seconds. Log_checkpoint_timeout was set to 120 and undo_retention to 150. The reason for the undo_retention setting was so that the use of undo could be guaranteed. I read somewhere that fast_start_mttr_target would override log_checkpoint_timeout. It's value is 300. Is that true?

The problem is now worse. The checkpoint via the log_checkpoint_timeout and one done manually (alter system checkpoint) do not write the dirty buffers to disk as they did in 8.1.7.4. Even running them serially or, at some times, hours later, resulted in ORA-01555.

I noticed in this article you mention 'it fires a log switch checkpoint, which will eventually, sometime, lazily
(maybe hours later) cause the block to be flushed to disk.'. I have seen Oracle documentation that refers to 'full' and 'incremental' checkpoints. Anything I do seems to result in incremental. How do I force a full checkpoint?

Any suggestions?

Tom Kyte
June 08, 2004 - 2:01 pm UTC

the amount of blocks checkpointed have nothing to do with an ora-1555.

log_checkpoint_timeout had nothing to do with this.


I'm not sure where you got the idea there is a tie in between undo_retention and log_*, fast_start_*???


checkpointing has *nothing but nothing* to do with ora-1555's.

the amount of undo retained has everything to do with ora-1555's.


If you have queries that run "for hours", you likewise need undo retention set to hours. What fixed your problem in 817 was:

Increasing rollback space,
segments,
and commit levels


what will fix it in 9i with AUM is:

Increasing rollback space, (creating large enought undo tablespace)
setting undo retention to be larger than the time it takes to run your longest running query
and commit levels


Are Dirty blocks the key to ORA-01555?

Mark Umbach, June 09, 2004 - 9:21 am UTC

Thanks for the response, but perhaps I was unclear. I was implying checkpoint and writing dirty blocks - not a relationship with redo. This is analygous to clearing the shared pool only to the buffer cache.

Unless I am totally confused or thinking in the wrong version of Oracle, I thought that the 'state' of a buffer block had everything to do with whether a 'rollback' or before-image was even visited. As long as dirty blocks are written out of the buffer there is no need for undo. The amount of undo needed has everything to do with what is needed by the current blocks in cache - that is unquestioned.

The solution in 8.1.7 consisted of the sizing stuff along with log_checkpoint_timeout a PL/SQL routine that was run between a couple of phases to clear the blocks so that the scheduled did not need to pause between jobs (waiting on the log_checkpoint_timeout). This routine simply did an alter system checkpoint. Before this was implemented there was literally always a problem with ORA-01555 between the DML job and the job that fetched from that table. The load job does updates along with inserts (lots of each) which means that the order that the blocks are used (and in rollback) is random. In that version we single-threaded the fact load job streams. Since the checkpoint was added between phases we have either been extremely lucky or the checkpoint forced the blocks to be written.

Oracle documentation Note 30755.1 (metalink) indicates 'LOG_CHECKPOINT_TIMEOUT specifies the amount of time, in seconds, that has passed since the incremental checkpoint at the position where the last write to the redo log (sometimes called the tail of the log) occurred. This parameter also signifies that no buffer will remain dirty (in the cache) for more than integer seconds.' This note is old (26-JUN-2001) but does contain 9i information. Is it completely invalid at this point?

I was using a combination of undo_retention to guarantee that the undo would be available (as long as the tablespace was big enough) and the checkpoint to allow overwriting of undo after I didn't need it (log_checkpoint_timeout).

This is definitely not the right was to go because of the incessant thrashing that this would cause DBWR to go through to force all dirty blocks to be written to disk.

It appears as though writing dirty blocks is completely asynchronous with any other process at this point and cannot be forced to clean point. I knew that there was always an asynchronous part of this but the attempt was to guarantee that the dirty blocks would be written at certain points in time.

Do you have any other possible solutions (other than redesign of the application/process)?

Is this making any sense? Am I dreaming?

Since these processes (12) are loading (inserts and updates) millions of rows each to many tables I need to provide a solution and disk to hold all of the undo is unreasonable. If there is no way in Oracle to make this happen I need to let folks know.

Your help is much appreciated.

Mark

Tom Kyte
June 09, 2004 - 10:03 am UTC

checkpoint and 1555 are 100% unrelated, totally. redo and 1555 are totally unrelated.

you have misunderstood -- yes.

If a query starts at time T0, ALL BLOCKS retrieved by the query will be "as of time T0". Regardless of where that block is (dirty in the buffer cache or sitting on disk clean). If the block retrieved from the cache|disk is "newer than time T0" (was updated *after* T0), the changes will be UNDONE (undo is processed to rollback the changes).

version is not relevant either. checkpoint, redo, dirty/clean, cached, on disk -- not relevant.

SCN of the block -- 100% relevant. If the SCN post dates the time your query began, you will be rolling back that block before reading it.


To avoid 1555 you

a) size undo

thats about it. checkpointing, redo -- not even part of the discussion surrounding 1555.


So, what you need to do is set undo_retention to be larger than the time you run your longest running queries for.

And ensure that sufficient undo space has been allocated (monitor v$undostat to see if you are prematurely expiring undo extents due to lack of space)

You use checkpointing to reduce recovery times in the event of a system failure, but they have *nothing* to do with 1555's at all. 1555 is all about UNDO, period.

dirty blocks

Mark Umbach, June 09, 2004 - 10:59 am UTC

Yes, Tom, I agree with everything that you have stated. Let me ask a couple of questions:

1. When dirty blocks (SCN postdates query TO) are read then UNDO is visited. True? (read consistent mechanism).

2. When DBWR writes blocks from cache, UNDO is not ever visited for that block (unless updated again - don't consider at this point). True? The header of the data block would not indicate that it has been changed.

3. When a query examines the header of the data block which indicates that it has been changed, the UNDO is visited even though the SCN predates the query. True? This is delayed block cleanout, I believe.

4. If #3 is true, then setting undo_retention greater that the longest-running query would not seem long enough since the undo could have been generated at a time that would not fall within the undo_retention timeframe. True? This is dependent, of course, on the size of UNDO and the activity.

5. If there are many updates in a process that reuse UNDO over and over that block may indicate that it has been changed (in cache) but the undo may not be available. True? This could be fetch across commits or delayed block cleanout.

6. If a checkpoint does not write all dirty blocks (header of the data block indicates that it has been changed), then Note 30755.1 is not true (This parameter, LOG_CHECKPOINT_TIMEOUT, also signifies that no buffer will remain dirty (in the cache) for more than integer seconds.) True?

It would seem that either sizing the UNDO extremely large or the block buffers very small would be the only way to get around delayed block cleanout unless writing all dirty blocks could be forced in some way.

Thanks . . . Mark

Tom Kyte
June 09, 2004 - 11:39 am UTC

1) not dirty -- when a block is read -- be it dirty, clean, cold, hot, red or yellow -- the scn is inspected. SCN is either "ok" or "not ok". if SCN OK -- you are done. If SCN not ok, undo changes to get it back to point in time when it was OK.


2) false.

t1: you start a query.
t2: someone updates block 5 in file 55.
t3: DBWR writes block out.
t4: you request block 5 from file 55. <<<=== you discover it post dates your T1
so you roll it back

you would get RANDOM answers from Oracle otherwise -- if "where the block was read from -- cache or disk" affected what data you saw.

the header of the block always contains the transaction information. Note that I did not mention if the update at t2 committed or not -- it is not relevant to the discussion (well, except that if the t2 transaction committed, we might get a 1555 at t4 -- if it did not commit, we could not get a 1555 at that point, we KNOW the undo exists)

3) no, the undo is visited only if it needs be. The block cleanout you are talking about is a different thing. It means dbwr flushed a block from the cache to the disk and the transaction that dirtied either

a) had not committed yet.
b) had committed but decided not to revisit the block to clean it out.

that means when the reader reads the block -- they are not sure if the block is "good enough" because there is "apparently" a transaction in flight against it. But when they do goto the rbs -- the find out "transaction committed". They then clean out the block -- so that subsequent readers don't hit that same issue, so they can just read the block.


if you have access to my book "Expert one on one Oracle" -- i cover this processing in detail with examples...


4) false.

5) undo retention corrects that issue. sizing rbs big enough without AUM corrects that issue.

6) the note is correct, your assumption that something magic happens to the block header during the flush is not.


actually setting block buffers very small would incurr even MORE delayed cleanouts as the threshold for cleaning out on commit is 10% of the buffer cache.

Actually, flushing the blocks out more rapidly will incurr even more delayed cleanouts as well -- since if the block was flushed, the transaction doing the commit will *not* be able to clean it out.

Thanks for setting me straight

Mark Umbach, June 09, 2004 - 5:58 pm UTC

Tom,

All of this was very helpful. I do have a copy of your book and use it frequently, though I did not on this occasion. I was focused in the wrong direction which your patience and book helped me get straight.

Thanks again

Thank you - Timely topic!

Rita, June 18, 2004 - 3:04 pm UTC

I have just run into this problem with 9.2. But I cannot seem to recover from it. Everytime I do "select *" on a particular tablespace I receive the 1555 error. My alert log has been showing 30036 "failure to extend rollback segment" as well.

Even though UNDO Tablespace is set to MAXSIZE UNLIMITED the UNDO_RETENTION parameter may be the cause. I increased this paramter but still had the problem.

I have another UNDO tablespace that I can use (ALTER SYSTEM SET...) but I'm not sure this will be successful if the current UNDO Tablespace is somehow corrupted.

Any thoughts?



Tom Kyte
June 18, 2004 - 3:36 pm UTC

and how full is your disk that these files are on.

Thanks for response

Rita, June 21, 2004 - 8:57 am UTC

Disk is about 20% full. The initial size of UNDO File is 200M. That is about 60% full but the maxsize is unlimited.

Tom Kyte
June 21, 2004 - 9:34 am UTC

is it set to autoextend.

if you are getting failed to extend
and you have plenty of disk space
then the answer is "autoextend is not enabled"

you need to either

o enable autoextend
o alter the files to make them bigger.

Dreaded ORA-00600

A reader, June 21, 2004 - 11:16 am UTC

Now I'm getting this error each time I do a "SELECT count(*) ...". BTW, the AUTOEXTEND was set to ON for the UNDO files. The error references "bad dscn" which I suspect means the data it is looking for in the logs has been overwritten (link to transactions is lost).

It doesn't seem like switching UNDO Tablespaces would correct this problem?

Tom Kyte
June 21, 2004 - 1:57 pm UTC

ora-600 = contact support. you have a problem, it is not "normal", it is not data being overwritten. it is something else.

undo_retention

A reader, July 30, 2004 - 9:10 pm UTC

I am still confused about undo_retention, how it works and how it affects the 'unable to extend' error.

From earlier on this page,

3. So if my understanding is correct, a high UNDO_RETENTION can increase the likelihood of "Unable to Extend Tablespace UNDO..." errors - right?

You said

"2) here undo_retention had nothing to do with it. The issue was the RBS you were assigned to could not grow to accomodate the work you needed to perform. It mattered not if undo_retention was 1 second or 5 days -- your transaction had a need to generate gobs of UNDO and was unable to since you limited the rbs to 4gig.

If you had been assigned to the "larger" allocated rbs, it would have run longer and if there had been sufficient space.

"Unable to extend happens because you run out of space. Period. If you set a high undo retention -- you are asking us to use more space. If you ask us to use more space then you give us, we'll be unable to extend. (a circular argument...) "

Questions:

1. What does setting a high undo_retention do exactly? You say 'asking us to use more space'. Is this really accurate? UNDO is a circular structure. When a transaction needs undo, it has 2 options: a) reuse already allocated extents or b) extend a segment.

How does undo_retention come into play when deciding whether Oracle goes for (a) or (b)? Since undo_retention is a suggestion, not a guarantee, if I have it to set to a unrealistically high number like 1000 days, it should be effectively the same as setting it to 0, right? If not, why not?

Everything else remaining the same, if a transaction gets 'unable to extend', I reduce undo_retention and re-run the same transaction and it succeeds! How is this explained? Since UR is not a gurantee, why didnt Oracle simply re-use existing extents instead of trying to extend the segment? [The fact that reducing undo_retention and re-running succeeded proves that my rbs is sufficient for my transaction]

I guess what I cant understand is that 'undo_retention' shouldnt come in the way of anything (since it isnt a guarantee), but it does appear to.

2. From what I remember in my class, the instructor said that in AUM, Oracle can "steal" extents from another rollback segment if needed. Is this true?

3. Are the undo segments in AUM managed similarly to temp segments in tempfiles? similarly or identically? What are the differences?

Thanks a lot

Tom Kyte
July 31, 2004 - 11:55 am UTC

undo_retention -- you tell oracle "i'd like to keep undo for a certain period of time, say 1 hour"

what that means is, if you ran a transaction at noon -- it generated some undo (rollback data).  if undo retention was set to an hour, Oracle will try to retain that undo -- not overwrite it -- for at least an hour.  It might overwrite it -- if you are pressured for space, but it will try to keep it for an houur (in 10g, you can force it to keep it -- by making transactions that want to overwrite fail instead of overwriting it)


1) setting a high undo retention means you are saying to Oracle -- PLEASE try to keep this undo for N hours.  Oracle will extend undo segments as much as possible as it needs space in order to accomodate that request.  If it cannot extend anymore (undo tablespace is full and no autoextend is possible on the datafiles) -- it will prematurely expire the oldest undo data in that segment -- meaning the undo retention request you made will not be observed.


with undo retention -- the option to reused already allocated extents is not so simple.  You will reused an already allocated extent IF it contains no transaction data that falls in the retention period.  If you have a 1 hour retention and you find an already allocated undo extent that contains undo for a transaction performed 59 minutes ago -- Oracle will not use that extent unless *forced* to by an out of space condition.


Setting undo retention artifically high will cause undo segments to grow until there is no more space available.  If you set up a 32gig undo segment and set 

a) undo retention to 1 hour
b) undo retention to 1 day

come back in a day and tell me how much undo data you have in each case.  One would *probably* have much less than 32gig allocated (i'm assuming you generate less than 32gig of undo per hour) the other would probably have 24times or more as much undo as a) does


2) it happens like this, when another extent is needed in an undo segment then:

1. first we try to allocate a new extent using free space (or autoextend space) in the undo tablespace

2. if this fails, AUM looks at expired extents in other undo segments (extents that contain undo for transactions that happened longer ago than the undo retention period).  when it finds one, it'll "steal" it -- take it over.

3. if this fails, it looks at unexpired extents in it's own segment (the oldest extent it has) and will prematurely expire that one and reuse it (meaning we've just blown the undo retention)

4. if that fails, it'll try to steal an unexpired extent from some other undo segment

5. and finally, if we get here, well, you are "out of luck" and "out of space"



3) no -- not at all.  they are managed almost just like rollback segments using manual undo -- were you specify how many rbs's to have, how big their extents are, and how big each rbs is.  They just have the additional ability to extend because of the retention policy (manual undo will only extend in response to a transaction needing more space -- aum will extend in response to that as well as "time") and move extents around (between segments)



<b>i thought it would be vaguely interesting to see an extent "move" from segment to segment so I setup a test to do so...</b>



ops$tkyte@ORA9IR2> create undo tablespace undo_test
  2  datafile size 2m
  3  /
 
Tablespace created.
<b>starting with a small undo tablespace (undo retention is set to 10800 -- "big")</b>

 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> alter system set undo_tablespace = undo_test
  2  /
 
System altered.
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> drop table t;
 
Table dropped.
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> create table t ( x int, y char(2000) );
 
Table created.
 
ops$tkyte@ORA9IR2> insert into t values ( 1, 'x' );
 
1 row created.
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> declare
  2      l_cnt number;
  3  begin
  4      loop
  5          update t set y = substr( y, 3 ) || to_char(sysdate,'ss');
  6          commit;
  7          select sum(blocks) into l_cnt from dba_free_space where tablespace_name = 'UNDO_TEST';
  8          exit when l_cnt is null;
  9      end loop;
 10  end;
 11  /
 
PL/SQL procedure successfully completed.

<b>we fill it up -- make it allocate all of the way out to 2meg. It cannot grow anymore, no autoextend and it is full</b>
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> drop table snap;
 
Table dropped.
 
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> create table snap
  2  as
  3  select segment_name, extent_id, blocks
  4    from dba_extents
  5   where tablespace_name = 'UNDO_TEST'
  6  /
 
Table created.

<b>save the "configuration" of the undo segments -- their extents and sizes..</b>
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> /* in another session, do something, a transaction and don't commit it */
ops$tkyte@ORA9IR2> pause

<b>here, I went off and did "update emp set ename = ename" and left it there, we just grabbed an extent in an undo segment and won't release it -- we will not be able to advance back into this one when we start doing lots of work below because of the uncommitted transaction</b>

 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> declare
  2      l_cnt number;
  3  begin
  4      for i in 1 .. 5000
  5      loop
  6          update t set y = substr( y, 3 ) || to_char(sysdate,'ss');
  7          commit;
  8      end loop;
  9  end;
 10  /
 
PL/SQL procedure successfully completed.

<b>so, we did lots of updates..</b>
 
 
ops$tkyte@ORA9IR2> column segment_name format a11
ops$tkyte@ORA9IR2> select coalesce( a.segment_name, b.segment_name ) segment_name,
  2         coalesce( a.extent_id, b.extent_id ) extent_id,
  3         a.blocks, b.blocks,
  4         case when a.segment_name is null then 'Moved Here'
  5              when b.segment_name is null then 'Moved Away'
  6          end what
  7    from snap a FULL OUTER JOIN
  8             (select *
  9                from dba_extents
 10               where tablespace_name = 'UNDO_TEST') b
 11         on (a.segment_name = b.segment_name and a.extent_id = b.extent_id)
 12   order by 1, 2
 13  /
 
SEGMENT_NAM  EXTENT_ID     BLOCKS     BLOCKS WHAT
----------- ---------- ---------- ---------- ------------------------------
_SYSSMU10$           0          7          7
_SYSSMU10$           1          8          8
_SYSSMU10$           2          8          8<b>
_SYSSMU10$           3                     8 Moved Here</b>
_SYSSMU11$           0          7          7
_SYSSMU11$           1          8          8
_SYSSMU11$           2          8          8
_SYSSMU11$           3          8          8
_SYSSMU12$           0          7          7
_SYSSMU12$           1          8          8
_SYSSMU12$           2          8          8
_SYSSMU12$           3          8          8
_SYSSMU13$           0          7          7
_SYSSMU13$           1          8          8
_SYSSMU13$           2          8          8
_SYSSMU13$           3          8          8
_SYSSMU14$           0          7          7
_SYSSMU14$           1          8          8
_SYSSMU14$           2          8          8<b>
_SYSSMU14$           3          8            Moved Away</b>
_SYSSMU15$           0          7          7
_SYSSMU15$           1          8          8
_SYSSMU15$           2          8          8
_SYSSMU15$           3          8          8
_SYSSMU16$           0          7          7
_SYSSMU16$           1          8          8
_SYSSMU16$           2          8          8
_SYSSMU16$           3          8          8
_SYSSMU9$            0          7          7
_SYSSMU9$            1          8          8
_SYSSMU9$            2          8          8
_SYSSMU9$            3          8          8
 
32 rows selected.
 

<b>and we can see that an extent (at least an extent) moved from 14 to 10...</b>


 

Monitoring undo_retention

A reader, July 30, 2004 - 9:14 pm UTC

Oracle 9iR2 has many advisories and v$ views to help to monitor and fine-tune various areas i.e. size them using your best guess and monitor it over time and change accordingly.

Are there any ways to monitor undo_retention? i.e. how many times did undo_retention get in the way of queries/transactions? If I reduce/increase undo_retention, what would the impact be on my transactions, sort of like the other v$..._advice views?

Thanks

Tom Kyte
July 31, 2004 - 12:01 pm UTC

v$undostat


search for that on this site to see to usage of it -- but it is documented in the reference guide as well.

A reader, July 31, 2004 - 5:45 pm UTC

Thanks, that clarified some stuff, but I still dont understand the following

"Everything else remaining the same, if a transaction gets 'unable to extend', I reduce undo_retention and re-run the same transaction and it succeeds! How is
this explained? Since UR is not a gurantee, why didnt Oracle simply re-use existing extents instead of trying to extend the segment? [The fact that reducing undo_retention and re-running succeeded proves that my rbs is sufficient for my transaction]

I guess what I cant understand is that 'undo_retention' shouldnt come in the way of anything (since it isnt a guarantee), but it does appear to"

Are you saying that when I reduced undo_Retention and re-ran my transaction, it succeeded just by co-incidence? i.e. because the other load on the database was different? So, reducing undo_retention was NOT the only thing that made it work?

alter system set undo_retention=1 day
<start transaction>
transaction fails with unable to extend

alter system set undo_retention=1 hour
re-rerun transaction
it succeeds.

Does it succeed in the second instance 100% because of reducing undo_retention? If yes, that contradicts the statement that UR is NOT a guarantee, since Oracle DID try to honor the setting at the cost of getting the 'unable to extend' error.

Thanks

Tom Kyte
July 31, 2004 - 6:11 pm UTC

the person that reduced the undo retention and re-ran got what is known as "false causality"

they would have succeeded regardless of the undo retention. someone else must have committed! or someone else was not doing some really big work. or the load was just totally different.

something else was at cause here, the retention didn't do it.

A reader, July 31, 2004 - 9:26 pm UTC

Questions mingled with your response:

ops$tkyte@ORA9IR2> select coalesce( a.segment_name, b.segment_name )

1. This is the same as using NVL(a.segment_name,b.segment_name), right? COALESCE() would make sense/look better only when we have >2 arguments, wouldnt it?

segment_name,
2 coalesce( a.extent_id, b.extent_id ) extent_id,
3 a.blocks, b.blocks,
4 case when a.segment_name is null then 'Moved Here'
5 when b.segment_name is null then 'Moved Away'
6 end what
7 from snap a FULL OUTER JOIN
8 (select *
9 from dba_extents
10 where tablespace_name = 'UNDO_TEST') b
11 on (a.segment_name = b.segment_name and a.extent_id = b.extent_id)
12 order by 1, 2
13 /

2. How does this query prove that the extent moved between segments?

3. Why is the FULL OUTER JOIN needed here? Is there a way to write this query without it?

"the person that reduced the undo retention and re-ran got what is known as "false causality"

Oracle is a very complex beast and sizing the various areas has been one of the most challenging areas of DBA work. Oracle 9iR2 has made great strides in automating lots of stuff and providing advisories to help incrementally tune. I love the SGA and PGA sizing methodology. Set it to 80/20 or some ratio based on your physical RAM, let the DB run for a while, monitor the various v$ advice views and change dynamically. Perfect. Heck, Oracle 10g almost has ALTER DATABASE AUTO!

That said, AUM still seems a little different.

In the discussion above, yes, I agree that reducing UR and succedding is "false causality", but let me put it this way.

I am a DBA running my database in AUM mode. I set my RBS size and undo_retention based on known requirements and after sizing for longest running query, flash back requirements, etc, etc.

Now I get the 'unable to extend' error. What is the right response to this? Increase the size of my RBS tablespace or reduce undo_retention? What facts/stats can I use to base my decision on?

Thanks

Tom Kyte
August 01, 2004 - 10:35 am UTC

1) sure, same as decode( a, null, b, a ) or case when a is null then b else a end or .........


2) an extent disappeared from segment "foo" and an extent appeared in segment "bar". given that there really isn't optimal on for AUM.


3) I wanted to see ALL records from before, and ALL records after. that is the very natural of a FOJ -- to show all records from all row sources. without the full outer join, an outer join could have shown all of the records from before and their matches after (but we would just have seen an extent "disappear"). an outer join the other way would have show all of the records after -- but not all of the records from before (so we would only have seen an extent "appear").

A union all of an outer join of BEFORE to AFTER, with an "anti-join" of AFTER to BEFORE (only keeping records where before.segment_name is null) would have been equivalent.



Why does AUM seem a little different? there is an advisor in EM and v$ views that you can ask "given my load, if I want to retain N units of time of undo -- what size disk do I need". Also, it (for the first time) flags the occurrences of ora-1555 (meaning your undo retention is too small or the amount of disk youve supplied is too small) allowing you the dba to detect this issue without and end user letting you know about it first.


the unable to extend in your case means "i didn't think about the duration of my longest running transaction (eg: if you update a row at noon and you continue 'transacting', and you commit at 1pm -- you better have allocated enough space to survive without reusing those extents for 1 hour -- perhaps you set undo_retention to the length of the longest running query, when it needs to be max( length of long running query, length of long running transaction) and optimally really -- length of long running query PLUS length of long running transaction.

Or it could be you have the occasional (or frequent) "monster transaction" that eats gobs of undo -- you need more space.


A reader, August 01, 2004 - 9:57 pm UTC

"there is an advisor in EM and v$ views that you can ask "given my load, if I want to retain N units of time of undo --
what size disk do I need". Also, it (for the first time) flags the occurrences of ora-1555 (meaning your undo retention is too small or the amount of disk youve supplied is too small) allowing you the dba to detect this issue without and end user letting you know about it first"

Great, thanks, a few final questions, if you dont mind.

1. We dont use EM yet, is v$undostat the view that you can ask the question "If I want to retain..."? Any other views related to this?

2. Where exactly does it flag the occurence of ORA-1555? And how can it be before the end user gets it first? Does it *predict* that ORA-1555 will happen?



Tom Kyte
August 02, 2004 - 7:52 am UTC

1) yes, v$undostat. there is an undoblks column that tells how many undo blocks are consumed in a unit of time (begin/end time are there). Just "multiply"

2) when you get an ora-1555 ssolderrcnt in that view is maintained. it is not that it predicts the occurence, it is that it notifies the dba -- without having to wait for end users to get frustrated enough to notify the dba. the dba can see there is an issue and correct the issue before your helpdesk says "hey guys, there is an issue"

OK

Siva, August 02, 2004 - 9:02 am UTC

Dear Sir,
Is there any difference between rollback segment header and
other segment headers?
Bye!


Tom Kyte
August 02, 2004 - 9:15 am UTC

sure, they are segment headers for different things. yes, a rbs segment header is different from say an index segment header or a temporary segment header.

Bugs in SMU

A reader, August 02, 2004 - 10:58 am UTC

I just went back to my alert log and saw

Wed Jul 28 23:00:41 2004
Failure to extend rollback segment 22 because of 30036 condition
FULL status of rollback segment 22 set.

And my batch job that got the ORA-30036 started at Wed Jul 28 22:47:55 2004.

My RBS tablespace is 2GB in size. I am positive that my database had no other active transactions at that time that would have made AUM not be able to get extents from other rollback segments.

Basically, following the steps you outlined above, there is no way that the transaction should have failed with a ORA-30036.

Quick search on Metalink and sure enough there are many bugs around this feature.

Search for ORA-30036 on Metalink, bugs are

3229141
2900863
2621669

The workaround for a few of these bugs do indeed recommend reducing undo_retention as a possible course of action.

Anyway, your explanations were extremely useful to understand how stuff (is supposed to) works, but it appears that are a few bugs around AUM in 9.2.0.4 that resulted in the behaviour that I saw.

Thanks

Tom Kyte
August 02, 2004 - 11:11 am UTC

3229141 is really an enhancement - if we tried to allocate N blocks and failed -- but we would have succeeded with N/2 or something -- we did not try the smaller increment. (and you can apply this to 9204...) Makes no mention of retention.




2900863 is about v$undostat not being updated when no space error is hit the first time. no mention of retention again. Nothing to do with AUM failing to allocate space when it should -- rather, AUM not updating a v$ view so you could see the failure occurred historically.

2621669, fixed in the 9203 and above patchset, was a case where a "steal" that could have happened, would under certain circumstances not happen. It is fixed and the other "workaround" was "add space" -- rather than decrease undo retention.

Bugs in SMU

A reader, August 02, 2004 - 12:24 pm UTC

Ok look at Note 247184.1. It clearly suggests reducing undo_retention as a fix to ORA-30036.

From our discussion so far, you claim (and prove of course) that reducing undo_retention is NOT the solution for ORA-30036. So why does this note suggest otherwise?

Regarding Bug 2621669, it does say that it is fixed in 9.2.0.3, but the symptoms I am seeing (in 9.2.0.4) are identical. My RBS has lots of free space, just a couple of transactions in the database other than the one that fails. Instead of getting ORA-30036, the txn should have grabbed an extent from some other segment or the same segment or something. The database did not have 2GB of active transactions at that time, no way. I will see if I can reproduce this (doubtful) and open up a TAR

Also, look at Bug 2053110. This is also claimed to be fixed by 9.2.0.4 yet I am seeing otherwise.

My gut feeling is that I am seeing Bug 2621669 and it is not properly fixed.

Thanks

Tom Kyte
August 02, 2004 - 1:02 pm UTC

the note is incorrect in its conclusion if you ask me. all that would do is defeat the purpose of undo retention. the side effect of setting the undo retention smaller is to allow the undo segments to have lots more "expired" extents that it can steal, either from themselves or from other segments. Nothing more.

It would be more pratical to increase the amount of undo available.

you don't need 2gig of active transactions -- you just need one or two teeny tiny ones. if someone is active -- that extent cannot be "stolen". the "blocking" transaction needs to be using a single byte of undo -- that is all.

2gig -- sounds 2 small.

Bugs in SMU

A reader, August 02, 2004 - 1:58 pm UTC

"you don't need 2gig of active transactions -- you just need one or two teeny tiny ones. if someone is active -- that extent cannot be "stolen". the "blocking" transaction needs to be using a single byte of undo -- that is all"

Right, but all this is at the extent level. So, the transaction that failed was unable to find even a single unused extent that it could steal/reuse/whatever among all the extents across the 25 _SYSSMUxx$ segments in my 2GB RBS tablespace! Knowing my database, this is simply not possible. It is just not that dynamic. Hence my gut feeling that this is still one of the SMU-related bugs that was claimed to be fixed in releases <= 9.2.0.4

Unfortunately, I dont see how I can reproduce it in a controlled fashion so as to file a bug report with Support.

Thanks

Tom Kyte
August 02, 2004 - 3:32 pm UTC

depends on which extent is grabbed. remember -- it is all about rings here. I believe we can only "steal" the last extent and slide those around (and remember, with manual undo, there is no stealing at all! so even if it does not steal every possible time you imagine it could -- it does have the ability to steal, something manual undo cannot do at all)


Bugs in SMU

A reader, August 02, 2004 - 4:21 pm UTC

Hm, if AUM can indeed only steal the last extent from every segment, it is not as smart as I thought. I thought that the entire RBS (all extents in all segments) are available for stealing as long as they dont have active transactions in them (and expired/unexpired depending on my undo_retention setting, of course).

It is definitely better than anything Oracle had so far. No more deciding number, size of rollback segments, just give it N GB and off you go.

Does 10g have any improvements in this area?

Oh well...Thanks for your time.

Tom Kyte
August 02, 2004 - 6:15 pm UTC

ok, i had to prove myself wrong :)

and I did.


setup the two meg undo tablespace.


found out my undo segment numbers (select segment_name from dba_segments where tablespace_name = 'UNDO_TEST') and did this:


drop table names;
create table names
as
select segment_name
  from dba_segments
 where tablespace_name = 'UNDO_TEST';
                                                                                


when I found out my segments were 9, 10, 11, ... 16 I ran this script

SQL> @uselast 10 16



--------------------------- uselast.sql -----------------------------
define usn=&1
define maxusn=&2
                                                                                
                                                                                
column extent_id new_val eid
                                                                                
declare
    l_eid number;
    l_xidusn number;
    l_ext number;
begin
    select max(extent_id) into l_eid
      from dba_extents
     where tablespace_name = 'UNDO_TEST'
       and segment_name =  '_SYSSMU&usn.$';
                                                                                
    loop
        update names
           set segment_name = segment_name
         where segment_name = '_SYSSMU&usn.$';
                                                                                
        select xidusn, start_uext into l_xidusn, l_ext
          from v$transaction
         where addr = ( select taddr
                          from v$session
                         where sid = (select sid
                                        from v$mystat
                                       where rownum = 1 )
                      );
        exit when ( l_xidusn = &usn and l_ext = l_eid );
        commit;
    end loop;
end;
/
                                                                                
select xidusn, start_uext
  from v$transaction
 where addr = ( select taddr
                  from v$session
                 where sid = (select sid
                                from v$mystat
                               where rownum = 1 )
                      );
                                                                                
column cmd new_val cmd
select decode( &usn,
               &maxusn, '',
               'sqlplus / @uselast ' || (&usn+1) || ' ' || &maxusn ) cmd
  from dual;
                                                                                
host &cmd
--------------------------------------------------------------

that grabed the last extent of all but the first undo segment (segment 9).


I then used:


define usn=&1
                                                                                
declare
    l_xidusn number;
    l_ext number;
begin
    loop
        update names
           set segment_name = segment_name
         where segment_name = '_SYSSMU&usn.$';
                                                                                
        select xidusn, start_uext into l_xidusn, l_ext
          from v$transaction
         where addr = ( select taddr
                          from v$session
                         where sid = (select sid
                                        from v$mystat
                                       where rownum = 1 )
                      );
        exit when ( l_xidusn = &usn and l_ext = 0 );
        commit;
    end loop;
end;
/
                                                                                
select xidusn, start_uext
  from v$transaction
 where addr = ( select taddr
                  from v$session
                 where sid = (select sid
                                from v$mystat
                               where rownum = 1 )
                      );
---------------------------------------------------------------


to use rbs 9 and issued a big update in that session (it kept the transaction active in that segment).

So now the script:
break on segment_name skip 1
select segment_name, extent_id, blocks
  from dba_extents
 where tablespace_name = 'UNDO_TEST'
 order by segment_name, extent_id
/
                                                                                
select xidusn, start_uext from v$transaction order by 1;

returns:


SEGMENT_NAME                    EXTENT_ID     BLOCKS
------------------------------ ---------- ----------
_SYSSMU10$                              0          7
                                        1          8
                                        2          8
                                        3          8
 
_SYSSMU11$                              0          7
                                        1          8
                                        2          8
                                        3          8
                                        4          8
 
_SYSSMU12$                              0          7
                                        1          8
                                        2          8
                                        3          8
 
_SYSSMU13$                              0          7
                                        1          8
                                        2          8
                                        3          8
 
_SYSSMU14$                              0          7
                                        1          8
                                        2          8
                                        3          8
 
_SYSSMU15$                              0          7
                                        1          8
                                        2          8
                                        3          8
 
_SYSSMU16$                              0          7
                                        1          8
                                        2          8
 
_SYSSMU9$                               0          7
                                        1          8
                                        2          8
 
 
31 rows selected.
 
 
    XIDUSN START_UEXT
---------- ----------
         9          0
        10          3
        11          4
        12          3
        13          3
        14          3
        15          3
        16          2
 
8 rows selected.

showing segment 9 has three extents and we are busy using the last extent of each of the existing rbs's.

Now I issued a "big" update:


ops$tkyte@ORA9IR2> update t set object_name = lower(object_name);
update t set object_name = lower(object_name)
       *
ERROR at line 1:
ORA-30036: unable to extend segment by 8 in undo tablespace 'UNDO_TEST'
 



and reran the queries against dba_extents and v$transaction:


ops$tkyte@ORA9IR2> @test
 
SEGMENT_NAME                    EXTENT_ID     BLOCKS
------------------------------ ---------- ----------
_SYSSMU10$                              0          7
                                        1          8
                                        2          8
 
_SYSSMU11$                              0          7
                                        1          8
                                        2          8
 
_SYSSMU12$                              0          7
                                        1          8
                                        2          8
 
_SYSSMU13$                              0          7
                                        1          8
                                        2          8
 
_SYSSMU14$                              0          7
                                        1          8
                                        2          8
 
_SYSSMU15$                              0          7
                                        1          8
                                        2          8
 
_SYSSMU16$                              0          7
                                        1          8
                                        2          8
 
_SYSSMU9$                               0          7
                                        1          8
                                        2          8
                                        3          8
                                        4          8
                                        5          8
                                        6          8
                                        7          8
                                        8          8
                                        9          8
 
 
31 rows selected.
 
 
    XIDUSN START_UEXT
---------- ----------
         9          0
        10          2
        11          2
        12          2
        13          2
        14          2
        15          2
        16          2
 
8 rows selected.


rbs 9 now has 10 extents -- it stole all but 3 from the existing rbs's.



Perhaps, if you are interested, you could write a procedure that when you get the unable to extent -- you select this data out into plsql variables (contents of dba_extents for the undo tablespace and contents of v$transaction) for a post mortem (after you rollback, you should be able to save that data) 

Thanks

A reader, August 02, 2004 - 10:07 pm UTC

Ok so you proved that AUM does indeed behave like I was hoping it would i.e. it "steals" any available extent from any of the currently allocated _SYSMU$ segments.

[Dont know how you manage to come up with these insanely brilliant proofs in such a short time, it will take me a day to go thru it and understand it!]

But now I am more convinced that I did experience a bug in AUM on 9.2.0.4. As you proved, the only way my transaction could get the ORA-30036 would be if it couldnt find even a single extent in any of my rollback segments that didnt contain an active transaction. Knowing my database, this is simply not possible. Unfortunately, I dont quite know how to go about reproducing it so that I can log a TAR.

[This is a little troubling, that there is a bug in basic functionality of a 9iR2 feature that is not fixed in the next-to-terminal release of 9i!]

I didnt quite understand your suggestion to save the details of the 'unable to extend' error for post mortem.

1. Do you mean a servererror trigger like...

create or replace trigger failed_to_extend
after servererror on database
declare
l_sql_text ora_name_list_t;
l_n number;
begin
if ( is_servererror(30036))
then
save the stuff from dba_extents, v$transaction, v$session, v$sql, etc into my error table
end if;
end;
/

2. Could you explain your comment about rollback?

Is a servererror trigger subject to the same "cant commit in a trigger" semantic like regular triggers are?

If so, I can simple make the servererror trigger an autonomous transaction, right?

Thanks

Tom Kyte
August 03, 2004 - 7:41 am UTC

when you hit the unable to extend -- and you are thinking "i am hitting this erroneously" -- you would save the contents of dba_extents for that tablespace and v$transaction (the entire row). then you could see the start/end extents each transaction was using (in v$transaction) and what extents were allocated to which segments. You'd be able to verify one way or the other the statment "there were extents to be stolen that were not stolen"


1) I would probably just code it as a procedure and call it in this one place -- were I was observing the issue. reason being -- we are out of rollback at this point, most likely this trigger cannot save persistently the data either (unless it used utl_file and printed a report or something like that)

2) you can use atrans in the server error, but if the error is "out of rollback...." (guess we could use insert /*+ append */ into unindexed tables -- no undo generated for that)



and remember -- by the time you grab v$transaction -- there is a good chance that "it is in a different state than when you hit the unable to extend" -- someone committed, someone new came into existence -- so there is a chance depending on how quick your transactions are, that we won't see an accurate picture everytime.

ora 1555 on select statment

ishams, August 30, 2004 - 3:16 pm UTC

One of my developer gating ora-1555 on select. They are using odbc driver. The error is below . Can you please help me. He keep asking me why i am gating ora 1555 on select not temp . I am using undo tablespace.
Pleas help me

ODBC-- call Failed.

[Microsoft][ODBC driver for Oracle][Oracle]ORA-10555:snapshot too old: rollback segment number 2 with name "_SYSSMU2$" too small (#155)



Tom Kyte
August 30, 2004 - 3:21 pm UTC

make sure the undo tablespace is large enough and that the undo retention is set to a number higher than the time it takes to run your longest running query.

Look at v$undostat to make sure you are not expiring extents prematurely (that would indicate you've allocated insufficient space)

look at the undo retention init.ora and make sure it is set "large enough"

ora-1555 on select

A reader, August 30, 2004 - 3:37 pm UTC

we are using following .
SQL> show parameter undo

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
undo_management                      string      AUTO
undo_retention                       integer     600
undo_suppress_errors                 boolean     TRUE
undo_tablespace                      string      UNDO_TBLS

The problem is this is third party applicaiton and we cant change retention size because they said may be some performance issue will start. 

One thing i dont understand why ora-1555 on select . Most of the time is showed on insert or update.
 

Tom Kyte
August 30, 2004 - 5:20 pm UTC

malarkey. increase it.

a 1555 is restricted to a select -- the select portion of an insert as select or the "select" portion of the update

update t set x = 5

think of that as if it were:


update ( SELECT * FROM T ) set x = 5;


same with delete. 1555 is a READ thing, not every a WRITE thing.


It is caused by one thing - insufficient amount of undo configured for your job.



If they think increasing it will affect performance -- what do they have to say about your current ZERO performance?!?


You currently have it configured for 10 minutes, 10 minutes either is INSUFFICIENT or if it is sufficient, you are expiring extents due to insufficient space allocated to the undo tablespace (v$undostat)


there is exactly two ways to avoid a 1555:

a) more undo so as to have sufficient undo lying about for read consistency
b) make your query faster (this is a viable alternative <<<======)




undo

Robert, September 03, 2004 - 11:21 am UTC

If I set autoextend ON for undo datafiles, would oracle extend the datafiles if it found that space in undo tablespace is not enough to support undo_retention? If it does, then it is a very useful feature as DBAs does not have to estimate how much space is needed in undo tablespace with regard to undo_retention. Thanks.

Tom Kyte
September 03, 2004 - 1:18 pm UTC

yes, it would extend the file in order to satisfy the undo_retention if possible/needed.

you would want to set a reasonable maximum

Undo - one more question

Rajendra Pande, September 03, 2004 - 5:58 pm UTC

Ref Metalink doc: </code> http://metalink.oracle.com/metalink/plsql/ml2_documents.showDocument?p_id=40689.1&p_database_id=NOT <code>
Note:40689.1

Section CASE 1 - ROLLBACK OVERWRITTEN

Session 1 starts query at time T1 and QENV 50 etc etc
Step 5 does a commit.
Then why is step 6 referring to QENV 50 (SCN 50) and not the SCN which is the SCN for this step 6 - after the commit in step 5.

Thanks

Tom Kyte
September 03, 2004 - 6:23 pm UTC

they are assuming a process like this:


for x in ( select * from t where x > 55 ) <<<== qenv "50"
loop
update t set c=... where pk= X.pk; <<<=== 1st iteration
updates that block "at scn 51"
commit; <<== commits

/* here, while we are looping, others are generating undo, assume the
for x in takes 10 minutes to run to the last row (also assume the last
row is on the same block as the "first row" was -- the first row
had x = 56, the last row has x = 100000000000, both > 55, both on the
same block though).

in the 10 minutes we were running, the undo we generated for the
very first row we processed was "nuked, overwritten, poofed away" --
it was allowed to be since we committed and released it for reuse
*/

So, we get ora-01555 at this point. Commiting in a cursor for loop does not "cause" 1555, but it is a great way to expose yourself to one (the cause of 1555 is "rollback is really too small". people say "commit often, saves on rollback -- but that is a *myth*, you really do need that rollback! else you 1555 yourself)


Clarification on "Commiting in a cursor for loop does not cause 1555"

AC, December 09, 2004 - 12:48 am UTC

Hello Tom,

Just want to make sure that I understand what you meant by "Commiting in a cursor for loop does not cause 1555".

Here's an example:

PROCEDURE undo_test_procedure
is
cursor c1 is select id, a, b, c
from huge_table;

BEGIN

FOR c1_rec in c1 LOOP
update table_a
set col_a = c1_rec.a
where col_a = c1_rec.id;

update table_b
set col_b = c1_rec.b
where col_b = c1_rec.id;

update table_c
set col_c = c1_rec.c
where col_c = c1_rec.id;

commit;

END LOOP;
END undo_test_procedure;

On this example, huge_table contains 10 million records, takes about 5 minutes to query. My undo_retention is set to 900 (15 minutes) and undo tablespace is sized at 1G.

Question is, would the procedure wait until the loop is done before closing the cursor and prevent other queries from re-using the undo segment the select query used? Are all the records going to be stored in c1 or just the records needed to run the update? I have hit ORA-1555 on a for (select) loop update commit end loop and thanks to this thread, realized why I'm hitting it. Also, if committing on every record exposes me to ORA-1555, how often should I commit on my sample procedure? Should I include a counter to commit every 10,000 records?

Thanks a lot for your time.

Transcation commited or rolled back when ORA-30036 occurs

A reader, August 24, 2005 - 8:29 pm UTC

Tom,
I would very much appreciate your response on the 2 questions below.

We are running an update on a table and received the following error

ERROR at line 1:
ORA-30036: unable to extend segment by 8192 in undo tablespace 'UNDOTBS1'
ORA-06512: at line 8

Oracle documentation mentions that undo tablespace is out of space and so we are getting this error.

My questions
1) When this error occurs, is the update transcaton(that caused this error) complete or will it be rolled back?
2) Is improper sizing of the undo tablespace the reason for this error(assuming there are no other transcations running in the DB).

Thank you


Tom Kyte
August 25, 2005 - 3:30 am UTC

1) the statement that failed is rolled back, the transaction is still active.

2) sure would seem that way, you have not configured sufficient undo tablespace space for the workload you perform.

How to avoid ORA-30036 and ORA-01555 in this situation

A reader, August 26, 2005 - 7:37 pm UTC

Tom,
The SQL below is generating a huge amount of undo.


DECLARE
v_count number(8) := 0;
CURSOR C1 IS SELECT MAS.ID ID1,MAS.USERID ID2, MAS.LOC_ID ID3
FROM USER_M MAS,USER_L LOG
WHERE MAS.USERID=LOG.USERID AND MAS.LOC_ID=LOG.LOC_ID;
BEGIN
FOR I IN C1
LOOP
UPDATE USER_L SET USER_M_ID=I.ID1
WHERE USERID=I.ID2 AND LOC_ID=I.ID3;
END LOOP;
COMMIT;
END;
/

Count of records in USER_L: 6 million
Count of records in USER_M: 2338

On executing the above SQSL, Got into ORA-30036(unable to extend segment by 8192 in undo tablespace 'UNDOTBS1') and ora-00257 (archiver error). The DBA took care of ora-00257 by increasing the archive log space. To fix the ORA-30036, we are commiting data more frequently(I understand from your book that frequent commits increase the time of execution).
When continued to get ORA-3006 error after changing the commit to every 10000 records.
We then changed the frequency of commit to every 1000 records. We now are getting ORA-01555(after 4 hrs of execution).

My question
1) How can we over come both these problems - ORA-30036 and ORA-01555.

Any comments of fixing this problem would be appreciated.

Thank you
DECLARE
v_count number(8) := 0;
CURSOR C1 IS SELECT MAS.ID ID1,MAS.USERID ID2, MAS.LOC_ID ID3
FROM USER_M MAS,USER_L LOG
WHERE MAS.USERID=LOG.USERID AND MAS.LOC_ID=LOG.LOC_ID and USER_M_ID is null;
BEGIN
FOR I IN C1
LOOP
UPDATE USER_L SET USER_M_ID=I.ID1
WHERE USERID=I.ID2 AND LOC_ID=I.ID3
and USER_M_ID is null;
v_count := v_count + 1;
if v_count = 1000 then
commit;
v_count := 0;
dbms_output.put_line('Commit done ');
end if;
END LOOP;
COMMIT;
END;
/


Thank you


Tom Kyte
August 27, 2005 - 5:22 am UTC

If you give me some simple create tables for the tables involved, I'll show you how to rewrite this as an update of a join (single sql statement) which will genearate the least amount of undo and redo (so less undo needed, but your DBA can in fact fix this by letting us have MORE undo space) and run faster (hence avoiding the 1555) and not committing until it is done (you are causing your OWN ora-1555 - you are the cause of the 1555!!! you are modifying the table you are reading and your read needs the undo you yourself are generating)

How to avoid ORA-30036 and ORA-01555 in this situation

A reader, August 27, 2005 - 9:58 am UTC

Create scripts for the tables involved listed below. Also found out from the DBA, that the undo tablespace was increased to 10g(from ?? - don't know), but we were still getting ORA-30036. The undo tablespace was then increased to 35G, but even before it could get any where close to the 35G, we got the ORA-01555.

Would appreciate it if you can provide the single SQL statement.

Thank you

--------------------------
CREATE TABLE USER_M
(
USERID VARCHAR2(16) NOT NULL,
USERNAME VARCHAR2(30) NOT NULL,
LOC_ID VARCHAR2(16) NOT NULL,
COMPANYID VARCHAR2(16),
EMPID VARCHAR2(16),
ID NUMBER NOT NULL
);


CREATE UNIQUE INDEX PK_USER_M ON USER_M(ID);

CREATE UNIQUE INDEX UNQ_USER_M ON USER_M(USERID, LOC_ID);

ALTER TABLE USER_M ADD (CONSTRAINT PK_USER_M PRIMARY KEY (ID));

ALTER TABLE USER_M ADD (CONSTRAINT UNQ_USER_M UNIQUE (USERID, LOC_ID));



CREATE TABLE USER_L
(
LOC_ID VARCHAR2(25),
USERID VARCHAR2(25),
DOCTYPE VARCHAR2(50),
DOCREFNO VARCHAR2(60),
DOCDATE DATE,
TRANSACTIONTYPE VARCHAR2(50),
SHIPMENTMODE NUMBER(1) DEFAULT 7,
TRANSACTION_DESC VARCHAR2(100),
ID NUMBER NOT NULL,
USER_M_ID NUMBER(16)
);

CREATE INDEX USER_L_N1 ON USER_L(DOCREFNO);

CREATE INDEX MIG_USER_L ON USER_L(USERID, LOC_ID);

CREATE UNIQUE INDEX PK_USER_L ON USER_L(ID);

ALTER TABLE USER_L ADD (CONSTRAINT PK_USER_L PRIMARY KEY (ID));

--------------------------


Tom Kyte
August 28, 2005 - 4:49 am UTC

ops$tkyte@ORA9IR2> update (
  2  SELECT MAS.ID new_user_m_id,  log.user_m_id
  3    FROM USER_M MAS,USER_L LOG
  4   WHERE MAS.USERID=LOG.USERID
  5     AND MAS.LOC_ID=LOG.LOC_ID
  6     and LOG.USER_M_ID is null
  7         )
  8     set user_m_id = new_user_m_id
  9  /


If user_m_id is indexed AND there are many thousands or more records planned to be modified, you might consider disabling the indexes, doing the update, and then rebuilding the indexes afterwards. 

Delayed Block Cleanout

Enayet, August 28, 2005 - 10:13 am UTC

Tom,

I am bit confused ... here is why:
(Expert 1-on-1: p191 - Delayed Block cleanout)

"....Oracle can determine that he transaction comitted long time ago, even though it's transaction slot has been overwritten in the rollback segment transaction slot."

1. How Oracle know that, please demystify ...
2. What is difference betwwen transaction table in data block and rollback segment?
3. What is transaction table, transaction slot .....

Tom Kyte
August 28, 2005 - 10:19 am UTC

1) because the transation is older than any known transaction, it is "old" - so old, it is before the oldest transaction that must be considered.


2) the transaction data on the block points to the rollback segment, where more information is found about the current status of the transaction. If a transaction modified 100 blocks, there will be 100 blocks pointing to the rollback segment information for that transaction - so no matter what block you hit of those 100 blocks, you go to a central place to find out if that transaction is "still going"

3) just consider it transaction information. Think of it like an array (table) of transaction records (slots) on a block, used to manage concurrent access to the data on the block.

Some doubts..

A reader, January 24, 2006 - 1:02 pm UTC

Hi Tom. Yesterday, we ran a cron job at 9 PM, the only thing this process does is that it updates a field on a 1.6M table. I checked our alert log today, and I found this entry:

Created Undo Segment _SYSSMU11$
Mon Jan 23 21:00:11 2006
Undo Segment 11 Onlined

Just wanted to make sure of the following:
I assume the available rollback segments at that moment was not sufficient to actually hold the undo data generated by the update, so oracle had to create yet another rollback segment in order to keep the modified data on the undo.

Is my assumption correct ?
Thanks!

Tom Kyte
January 24, 2006 - 8:57 pm UTC

automatic undo management will create new undo segments as the number of users goes up (and takes them offline as they go down). It is driven by the number of concurrent transactions - not so much the size of the transactions...

It was not that the existing undo segments were too small to hold this...

Rollback Segment tablespace

Sudershan, January 25, 2006 - 12:46 pm UTC

Database: 9i

Hi tom,
When Rollback tablespace is staying at 99%..been like that
for half a day or so
How do you find out the update staements that are causing that...
or start troubleshooting that...

Thanks


Tom Kyte
January 25, 2006 - 1:48 pm UTC

I would not expect your rollback tablespace to shrink back unless you were using optimal, but you shouldn't really use that

and in 9i, perhaps you should be using an UNDO tablespace.

but, why do you think that having your rollback segments allocated is a bad thing? It does not mean they are "full", just allocated and ready/waiting to be used...

undo

zammer, January 25, 2006 - 1:49 pm UTC

Tom,

What is the best way to find the value for undo_retention?

Tom Kyte
January 25, 2006 - 4:35 pm UTC

what is your longest running query?

you would generally want undo retention to exceed that tim.

v$undostat can be useful in seeing this (maxquerylen

UNDO_RETENTION

Greg, January 25, 2006 - 2:20 pm UTC

I'm not Tom, but how about:

SQL> show parameter undo_

NAME                                 TYPE        VALUE
--------------------------------------------------------
undo_management                      string      AUTO
undo_retention                       integer     10800
undo_suppress_errors                 boolean     FALSE
undo_tablespace                      string      UNDOTBS1
SQL>
 

Rollback Segments Allocated...

sudershan, January 25, 2006 - 2:54 pm UTC

9i
"but, why do you think that having your rollback segments allocated is a bad
thing? It does not mean they are "full", just allocated and ready/waiting to be
used... "

I was just wondering how you can tell what is allocated
vs what is really being used..
like to see if there is really some user..who ran this
huge update..and then left without rolling it back or committing it..

Tom Kyte
January 25, 2006 - 4:58 pm UTC

v$transaction - used_ublk - shows how much any transaction has and how long it's been having it.

undo retention

frank, January 25, 2006 - 5:11 pm UTC

I meant How to decide the undo retention value?

Tom Kyte
January 25, 2006 - 7:00 pm UTC

see above, I answered that already

Oracle DBA

Joe Franco, February 19, 2006 - 7:51 pm UTC

Sorry Tom for coming back to this issue but I have something very stange happening with one of our production databases.
I'm getting the normal ora 1555 but what I find "strange" is that the message does not include the undo name,like _SYSSMU1$. Here is the message: "ORA-01555: snapshot too old: rollback segment number with name "" too small on query ....". Tom, is it possible to for to clarify why the rbs is being referenced by ""?
This error does not happen all the time. Although the query that genetared the 1555 runs every 15 minuts, the problem when it happens is 95% of the time at the week end (Sunday).
We don't have anything else running at that time.
The query takes 2 minuts to run. The size of the undo tablespace is 2G and the undo retention period is 15 minuts. If we are to believe in the Oracle graph that the 9i Enterprise Manager generates the "undo space requirements estimate" based on the maximum undo generation rate is less than 85M.
Any help with this is most appreciated. Thaks Joe

Tom Kyte
February 20, 2006 - 7:51 am UTC

distributed query perhaps?


are there some long running transactions that normally aren't happening but happen to be taking place during this event?


How to identify the object in undo tablespace with “UNEXPIRED” status?

Leo Wang, February 23, 2006 - 6:13 pm UTC

Tom,

Our undo tablespace is growing fast and most of the space is used by the UNEXPIRED objects. We keep the undo_retention time to 3 hours. Below are the blocks used for undo.

SELECT
TABLESPACE_NAME,
STATUS,
sum(BLOCKS)
FROM DBA_UNDO_EXTENTS
group by TABLESPACE_NAME,STATUS
/

TABLESPACE_NAME STATUS SUM(BLOCKS)
-------------------- --------- -----------
UNDOTBS2 ACTIVE 512
UNDOTBS2 EXPIRED 270941
UNDOTBS2 UNEXPIRED 853770

By joining v$locked_object, dba_objects, dba_rollback_segs, v$transaction, and v$session, one can find the object name in undo with “ACTIVE” status. Is there any way to find the object name in undo with “UNEXPIRED” status? Thanks.


Tom Kyte
February 23, 2006 - 8:18 pm UTC

umm, whats the point - what are you trying to do?

You have asked for undo to be retained for 3 hours.

We will retain undo for 3 hours and then expire it. We can reuse that.

What are you trying to accomplish here?

Thanks for your help on UNDO

Ashish Mrig, April 26, 2006 - 9:46 am UTC

I just have a quick question -
We are building a brand new database in Oracle 9.2, what setting of the parameter UNDO_RETENTION should I start with ?
In other words how do I find out the optimal setting ?
Onve we have that value, we can fine tune it on basis of our tests.

Tom Kyte
April 27, 2006 - 4:08 am UTC

what is your estimation of your longest running query - that would be a starter.

Also, how far back would you like to be able to flashback query. On asktom, I've set it for many hours - so I can recover from "whoops" type operations without resorting to backups. That would be another thing to consider.

Surprised no-one has mentioned this...

Darren, June 05, 2006 - 7:05 pm UTC

Metalink Note:240746.1 which talks about how undo_retention works when set to 0 in 10g. Very interesting. It's not really detailled in the Reference entry for the parameter.

SELECT MAX(maxquerylen) FROM v$undostat t;

jas, July 06, 2006 - 1:23 pm UTC

if the output is 117870 should I set the parameter undo_retention as secs or millisecs

Tom Kyte
July 08, 2006 - 10:18 am UTC

documentation says

</code> http://docs.oracle.com/docs/cd/B19306_01/server.102/b14237/initparams221.htm#sthref898

"in seconds", you set undo retention in seconds.

documentation also says

http://docs.oracle.com/docs/cd/B19306_01/server.102/b14237/dynviews_2174.htm#sthref4159 <code>

maxquerylen is in seconds in v$undostat.

~33 hours, I'd be looking for that query and trying to "make it not take that long"?

undo retention guarantee

SM, July 10, 2006 - 4:05 pm UTC

Oracle Version 9206

Tom..
The following is from oracle 92 documentation..

"The effect of the UNDO_RETENTION parameter is immediate, but it can only be honored if the current undo tablespace has enough space for the active transactions. If an active transaction requires undo space and the undo tablespace does not have available space, the system starts reusing unexpired undo space. Such action can potentially cause some queries to fail with the "snapshot too old" error."

Question:
Let's say we seek 2 hours of undo retention...
and using the formula to estimate undo space (UndoSpace = UR * UPS + overhead)..say we get that we need about 2 gigs of space to honor this retention...and then say we assign about three gigs to undo space to guarantee undo retention.
Now..here is what I interpreted from the docs:
If active transactions need more than a gig that is available (aside from 2 gigs that is needed to honor our undo retention)..then the transaction will start using the
2 gigs...which means the undo retention is not guaranteed in that case correct?

Another question..is that how you estimate the undo space
(using the formula)..so you have a retention requirement..
and then you look at v$undostat table to get the other variables for the formula?

just curious..what is the retention set up for this site..
and how much space have you allocated for the undo?

Thanks

Tom Kyte
July 11, 2006 - 7:32 pm UTC

what you can say is

a) I have allocated 3gigs of undo
b) I have asked for 2 hours of undo to be saved.


IF you generate less than 3gig of undo in two hours, the undo retention will be honored.

if you generate MORE than 3gig of undo in two hours, some of the older undo will be prematurely expired and overwritten - we will not keep 2 hours of undo.


I have 12 hours set up with autoextend datafiles on undo.

Estimating space in undo tablespace

SM, July 10, 2006 - 7:17 pm UTC

Oracle 9206

So...if we seek a retention time of two hours..
we can just do this..right?:

select (max(undopersec) * 8 * 1024 * 7200) / (1024*1024*1024) undo_space_needed_in_gigs
from (
select
undoblks/((end_time - begin_time)*86400) UndoPerSec
from v$undostat
);

or..if we want to look at..only last 24 hours:


select (max(undopersec) * 8 * 1024 * 7200) / (1024*1024*1024) undo_space_needed_in_gigs
from (
select
undoblks/((end_time - begin_time)*86400) UndoPerSec
from v$undostat
where begin_time > (sysdate - 1)
);


Tom Kyte
July 11, 2006 - 7:46 pm UTC

why not use the undo advisor in enterprise manager?

because it does not work ?

f, July 12, 2006 - 4:07 am UTC

undo advisor does not work for me (never did),
always throwing exceptions like





Undo Management: Error
java.sql.SQLException: ORA-00600: internal error code, arguments: [ktfbhget-4], [6], [5], [], [], [], [], [] at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:111) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:330) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:287) at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:742) at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:215) at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:954) at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1138) at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:838) at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1224) at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3290) at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3334) at oracle.sysman.util.jdbc.PreparedStatementWrapper.executeQuery(PreparedStatementWrapper.java:653) at oracle.sysman.emo.adm.instance.undo.UndoAdvisoryBean.executeQuery(UndoAdvisoryBean.java:1358) at oracle.sysman.emo.adm.instance.undo.UndoAdvisoryBean.getTablespaceSize(UndoAdvisoryBean.java:1786) at oracle.sysman.emo.adm.instance.undo.UndoAdvisoryBean.initUndoInfo(UndoAdvisoryBean.java:695) at oracle.sysman.emo.adm.instance.undo.UndoAdvisoryBean.initUndoManagement(UndoAdvisoryBean.java:546) at oracle.sysman.db.adm.inst.undo.UndoAdvisoryDataSource.populateManagement(UndoAdvisoryDataSource.java:375) at oracle.sysman.db.adm.inst.undo.UndoAdvisoryController.deliverUndoManagementPage(UndoAdvisoryController.java:268) at oracle.sysman.db.adm.inst.undo.UndoAdvisoryController.handleEvent(UndoAdvisoryController.java:1030) at oracle.sysman.emSDK.svlt.PageHandler.handleRequest(PageHandler.java:376) at oracle.sysman.db.adm.RootController.handleRequest(RootController.java:169) at oracle.sysman.db.adm.DBControllerResolver.handleRequest(DBControllerResolver.java:114) at oracle.sysman.emSDK.svlt.EMServlet.myDoGet(EMServlet.java:688) at oracle.sysman.emSDK.svlt.EMServlet.doGet(EMServlet.java:291) at oracle.sysman.eml.app.Console.doGet(Console.java:285) at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at com.evermind.server.http.ResourceFilterChain.doFilter(ResourceFilterChain.java:65) at oracle.sysman.emSDK.svlt.EMRedirectFilter.doFilter(EMRedirectFilter.java:101) at com.evermind.server.http.EvermindFilterChain.doFilter(EvermindFilterChain.java:16) at oracle.sysman.db.adm.inst.HandleRepDownFilter.doFilter(HandleRepDownFilter.java:138) at com.evermind.server.http.EvermindFilterChain.doFilter(EvermindFilterChain.java:20) at oracle.sysman.eml.app.ContextInitFilter.doFilter(ContextInitFilter.java:269) at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:600) at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:317) at com.evermind.server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:793) at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:270) at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:112) at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:192) at java.lang.Thread.run(Thread.java:534)




and








Undo Management: Error
java.sql.SQLException: Closed Connection at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:111) at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:145) at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:207) at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:1075) at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:966) at oracle.sysman.util.jdbc.ConnectionWrapper.getDatabaseParameter(ConnectionWrapper.java:1888) at oracle.sysman.db.adm.inst.undo.UndoAdvisoryDataSource.populate(UndoAdvisoryDataSource.java:439) at oracle.sysman.db.adm.inst.undo.UndoAdvisoryController.deliverUndoPage(UndoAdvisoryController.java:402) at oracle.sysman.db.adm.inst.undo.UndoAdvisoryController.handleEvent(UndoAdvisoryController.java:1130) at oracle.sysman.emSDK.svlt.PageHandler.handleRequest(PageHandler.java:376) at oracle.sysman.db.adm.RootController.handleRequest(RootController.java:169) at oracle.sysman.db.adm.DBControllerResolver.handleRequest(DBControllerResolver.java:114) at oracle.sysman.emSDK.svlt.EMServlet.myDoGet(EMServlet.java:688) at oracle.sysman.emSDK.svlt.EMServlet.doGet(EMServlet.java:291) at oracle.sysman.eml.app.Console.doGet(Console.java:285) at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at com.evermind.server.http.ResourceFilterChain.doFilter(ResourceFilterChain.java:65) at oracle.sysman.emSDK.svlt.EMRedirectFilter.doFilter(EMRedirectFilter.java:101) at com.evermind.server.http.EvermindFilterChain.doFilter(EvermindFilterChain.java:16) at oracle.sysman.db.adm.inst.HandleRepDownFilter.doFilter(HandleRepDownFilter.java:138) at com.evermind.server.http.EvermindFilterChain.doFilter(EvermindFilterChain.java:20) at oracle.sysman.eml.app.ContextInitFilter.doFilter(ContextInitFilter.java:269) at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:600) at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:317) at com.evermind.server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:793) at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:270) at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:112) at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:192) at java.lang.Thread.run(Thread.java:534)






Tom Kyte
July 12, 2006 - 4:28 pm UTC

umm, one wonders why you never went to metalink then? problem exists, fix problem???

Undo_Retention

Parikshit Paul, July 27, 2006 - 5:41 am UTC

Hi Tom,
Just a simple question;;
Is there any use in keeping undo_retention>0 if we don't want to use flashback ?

Tom Kyte
July 27, 2006 - 11:53 am UTC

sure, you probably do want to avoid the ora-1555 snapshot too old :)

that is the main thing undo_retention is for.

Excuse me

Parikshit Paul, July 28, 2006 - 3:13 am UTC

But if i get you right, keeping undo_retention=0 would be right if i want to avoid ora 1555?

Tom Kyte
July 28, 2006 - 7:54 pm UTC

depends on how you have it set up.

Please explain

Parikshit Paul, July 29, 2006 - 5:33 am UTC

Could you be mre descriptive ? with examples

Tom Kyte
July 29, 2006 - 9:04 am UTC

see the docs, depends on whether you have a fixed sized undo tablespace or autoextend.



question in the auto undo

A reader, August 01, 2006 - 12:50 pm UTC

DB=9.2.0.7
I have set undo_retention 5 hours, which is 18000, undo_management=AOTU.
And set the datafile in the tablespace 1G with auto extend =ON.

I tested a long run delete and the datafile extended to 6 G when the delete completed. exited out and loged in, tried the same delete again. the datafile was just keeping grow beyond 6 G. Why Oracle does not reuse the space of the datafile since the older session existed out? There was only one session -me on the database.

Here is the statements of tablespace creation.
create undo tablespace PMDB_UNDOTS1
datafile '/S0P2PVT9/pmdb_undots1.dbf' size 1000m reuse
extent management local ;
alter database datafile '/S0P2PVT9/pmdb_undots1.dbf' autoextend on
next 1m maxsize 20000m;

Tom Kyte
August 01, 2006 - 7:12 pm UTC

because you said "KEEP 5 HOURS"

did you wait 5 hours?

A reader, August 01, 2006 - 7:27 pm UTC

<qoute
because you said "KEEP 5 HOURS"
did you wait 5 hours?
>
Not sure what you implied. did you mean: the datafile will grow upto 5 hours? after that time Oracle will reuse the space in the datafile?

My case was I ran the long delete, it took 2 hours to complete. the database file extended to 6 G from 1 G. Then I *loged out* and loged on to try the same loong delete. and agian it took 2 hours to complete and the datafile extended to 12 G.

I failed to understand why oracle did not reuse the space of the file on the repeat run of the delete.



Tom Kyte
August 02, 2006 - 10:58 am UTC

you said "my undo retention is 5 hours"

that means you want to keep all of the undo generated within the last 5 hours. Not until the undo is 5 hours and 1 minute old (or older) will we over write it.

So, you generated 6gig of undo.
Five hours HAS NOT PASSED since you generated it.
Hence we will KEEP IT as per your request.


It did not reuse it because you explicity asked it NOT to reuse it for five hours!!!!!

It may seem strange...

Mark A. Williams, August 01, 2006 - 9:19 pm UTC

It may seem strange, but the UNDO_RETENTION parameter is documented:

</code> http://download-east.oracle.com/docs/cd/B19306_01/server.102/b14237/initparams221.htm#sthref898 <code>

In particular:

For AUTOEXTEND undo tablespaces, ***the system retains undo for at least the time specified in this parameter...***

The link above has full details.

Now I would quibble with the phrase "For AUTOEXTEND undo tablespaces" as it implies that AUTOEXTEND is an attribute of a tablespace when it is an attribute of a datafile, but that is peripheral to the main point.

- Mark

questions

A reader, August 02, 2006 - 2:21 pm UTC

Tom,
5 hrs undo_retention, seems like it counts undo cumulatively for all the sessions. my case was consective (one after another) sessions. what heppens if 2 parallel sessions, both run 2.5 hrs undo? Does Oracle reuse the space after 2.5 hours after both complete?



Tom Kyte
August 02, 2006 - 4:03 pm UTC

forget sessions.

think "time"

it will retain all undo generated within the last 5 hours.
by any session
by any statement
it does not care about sessions, transactions, whatever

all undo generated in the last 5 hours, that is what you asked to be retained and it did so.

it'll reuse undo 5 hours after the undo was "finished"

A reader, August 07, 2006 - 2:14 pm UTC

Tom,

We are running into these Oracle errors after the query had been runing for 4 days:

ORA-12801: error signaled in parallel query server P014
ORA-01555: snapshot too old: rollback segment number 10 with name "_SYSSMU10$" too small

The thing is that while the query was executed, there was no transaction going on, although there was loading in a different schema. So why would we get this ORA-01555 error?

Thanks.

how to suppress ora 30019

Manish, September 20, 2006 - 9:14 am UTC

Hi Tom,
I recently moved from rbs to undo in 9205 and upgraded the same to 10202.
IN code they are using set transantion user rbs ...

In 9i the code blew out with ORA-30019 errors , while the same code ran successfully in 10g.

Both are in undo mode.

In 9i I have to use undo_suppress_errors=true and then it worked.

How come in 10g oracle took care of its own, also undo_suppress_errors is obsolete in 10g, can you please explain this.

In the long run we are going to get rid of this piece of code.

Thanks

Tom Kyte
September 20, 2006 - 3:17 pm UTC

explain what? that things change (things are made easier as they are observed to be "hard" over time?)

In 10g, they recognized that people did this, that the error should just be surpressed when using auto.

so you already know how to surpress it in legacy 9i databases, and you know you don't need it in 10g?



query for undo sizing

Jeff, October 12, 2006 - 10:45 am UTC

Tom,

We're running into occasional ora-1555 errors on some large batch jobs in our DW.
I found this query in a metalink note (262066.1) for determining undo ts sizing.

SELECT (UR * (UPS * DBS)) + (DBS * 24) AS "Bytes"
FROM (SELECT value AS UR FROM v$parameter WHERE name = 'undo_retention'),
(SELECT (SUM(undoblks)/SUM(((end_time - begin_time)*86400))) AS UPS FROM v$undostat),
(select block_size as DBS from dba_tablespaces where tablespace_name=
(select value from v$parameter where name = 'undo_tablespace'));

I if take the value from v$undostat:

SQL> select max(maxquerylen) from v$undostat;

MAX(MAXQUERYLEN)
----------------
           65956

So now I plug 65956 into the above query and get a value of about 1.8GB
This sounds grossly undersized to me.
Our db is a large data warehouse(about 800GB), with several long running queries.
The current retention is set to 7200 and ts size is 71GB.

Would setting undo_retention to 65956 and setting the undo ts size to 1.8GB help us avoid ora-1555 errors?
Is the query above reliable?

Would there be any negative impact to setting the retention to 65956 and leaving the undo ts at 71GB?

Thanks.
 

Tom Kyte
October 12, 2006 - 11:45 am UTC

why not use automatic undo management and forget about forumlas? it'll tell you how much undo you need for a given retention time.


If you want your jobs to actually execute, you would need to set the undo retention to what you need to set it to.

auto is set...

Jeff, October 12, 2006 - 11:53 am UTC

our undo management is set to auto.

>> "If you want your jobs to actually execute, you would need to set the undo retention to what you need to set it to."

That's what I'm trying to figure out with the queries. How do I know what to set it to? Is that 65956 number what I need to set it to?

Tom Kyte
October 13, 2006 - 6:34 am UTC

there is the undo advisor in EM

there is v$undostat

either of them could be used to determine the duration of your longest running query, set undo_retention a bit higher than that and provide sufficient disk to hold that much (either of the above will be useful in determining that size as well)

If I may....

A reader, October 12, 2006 - 1:01 pm UTC

Hi Jeff,
It may be useful for you if you can use the Undo Advisor available both in Statspack and Oracle Enterprise Manager Console.
I would advise the console as it is easier to comprehend and you do not have to wait for snaps. It givs a graph to help you understand the Undo performance for the database.

Just give it a shot.
Cheers


ORA-1555 with undo_retention=15 hours

SEan, October 17, 2006 - 11:07 am UTC

we are on 9207. use auto undo management.
undo_retention set 54000 (15 hours). after the application upgraded we hit 1555:
Tue Oct 17 09:47:40 2006
ORA-01555 caused by SQL statement below (Query Duration=3 sec, SCN: 0x0844.a034ea47):

checked the undo datafile. it is 3.5 GB but it is allowed to grow to 31G.

Do you think it was because undo_retention set low? we shall increase the undo_retention.

i know that the bad application cause, at this time i only want to fix w/o asking the software provider to fix the codes.

Tom Kyte
October 17, 2006 - 11:08 am UTC

could it be this:

</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:40115659055475#69911565592248 <code>

a flashback query that flashed too far back into the past.

A reader, October 17, 2006 - 12:46 pm UTC

Tom,
i read it. not sure how do we fix it? by increasing undo retention higher than 15 hours?

TIA.
Sean

Tom Kyte
October 17, 2006 - 1:19 pm UTC

"i read it"???


but anyway, one place to start would be to *find* the query wouldn't it? To see what it was and confirm it was flashing back and how far back it was going...

</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:40115659055475 <code>

Sean, October 18, 2006 - 11:41 pm UTC

Tom,
here was the query. not sure how the flashback query applies to.
ORA-01555 caused by SQL statement below (Query Duration=8 sec, SCN:
0x0844.99b07518):
Tue Oct 17 04:06:11 2006
SELECT "TASK_ID","PROJ_ID","TASK_TYPE","ACT_END_DATE" FROM "TASK" "T" WHERE
("TASK_TYPE"=:"SYS_B_0" OR "TASK_TYPE"=:"SYS_B_1") AND "ACT_END_DATE" IS NOT
NULL

Tom Kyte
October 19, 2006 - 8:12 am UTC

do they use serializable or read only transactions.

have you inspected v$undostat

have you thought about smacking the developers soundly about the ears for using cursor-sharing=force/similar.

Sean, October 19, 2006 - 10:01 am UTC

do they use serializable or read only transactions?

Not sure it is from the applications.

have you inspected v$undostat
it occurred undeterministic, had not occurred a last couple of days. doubt it was in v$undostat

have you thought about smacking the developers soundly about the ears for using
cursor-sharing=force/similar.

we set "force" in init.ora



Tom Kyte
October 19, 2006 - 2:02 pm UTC

... we set "force" in init.ora ....


I am so so very sorry for you, that is very sad.

2 Gig schema eating up 33 Gig of undo tablespace,

A reader, October 23, 2006 - 8:02 pm UTC

We have a stored procedure that does series of DML statements. The tables in that schema are not that big as the size of the entire schema is 2 Gig.

The size of the UNDO tablespace is 33 Gig and the value of UNDO_RETENTION is 60.

8 out of 10 times we get ORA-30036 error at one of the DML statement. If we run the DML statement separetly on SQL Plus it executes fine.

Each DML prior to that has a commit at the end (each DML runs in a loop and has commit at the end of the loop).

I suspect the error is because of UNDO_RETENTION.

Do you have an explanation to this?

Thanks,



Tom Kyte
October 24, 2006 - 12:33 am UTC

I suspect is has nothing to do with undo retention.

it is set to 60 seconds, which is tiny.



ORA-30036

Roderick, October 24, 2006 - 2:31 am UTC

If the DML affects indexes residing in an ASSM tablespace, then some versions of Oracle have a bug (e.g. 3857781) where a particular mix of activity can generate much more undo (and redo) than you'd expect. But I'm just pulling at straws here. Might be a good idea to present this case with a bit more detail to Support.

some more info,

A reader, October 24, 2006 - 3:11 pm UTC

Thanks for the input.  I have some more info about my UNDO tablespace which may help to give some tips to me.

SQL> select initial_extent,max_extents,next_extent,pct_increase from dba_tablespaces
  2  where tablespace_name='UNDO';

INITIAL_EXTENT MAX_EXTENTS NEXT_EXTENT PCT_INCREASE
-------------- ----------- ----------- ------------
         65536  2147483645

The tablespace is LOCALLY managed tablespace.

SQL> l
  1* select file_name,autoextensible from dba_data_files where tablespace_name='UNDO'
SQL> /

FILE_NAME                                AUT
---------------------------------------- ---
D:\ORADATA\SDCD\UNDO_01.DBF              YES


  1* select bytes,maxbytes,increment_by from dba_data_files where tablespace_name='UNDO'
SQL> /

           BYTES         MAXBYTES INCREMENT_BY
---------------- ---------------- ------------
  34,299,969,536   34,359,721,984           13



Today's job failed again for the same ora-30036 error.  I am suspecting the max_extents value which is 2 Gig is probably the reason.  Although the tablespace is 33 Gig, it may not grow beyond 2 Gig.

But I don't understand what the values of BYTES and MAXBYTES in dba_data_files stand for?

Please advise.

thanks, 

Tom Kyte
October 25, 2006 - 9:13 am UTC

bytes and maxbytes are documented:
</code> http://docs.oracle.com/docs/cd/B19306_01/server.102/b14237/statviews_3083.htm#sthref2011 <code>


ignore the dba_extents stuff, doesn't count (undo is 32k max extents anyway, and the extent sizes will grow as we add more extents)

basically, this is saying your undo space is 32gig, done, no more room.

cont...

A reader, October 25, 2006 - 2:35 pm UTC

Our application is running right now and the current status of undo tablespace is:

*m UNDO 33,496,064 15,331,648 18,164,416 45.8 4,063,232 33,554,416 99.8.

It has used 15 Gig of space so far.

I have an automated script that runs every minute and captures the used_ublk number from v$transaction and stores it in a table.

According to that (there are 85 rows but I am pasting last few of them):

SID_SERIAL UNDO_KB CURRENT_TIME
---------- ------------ --------------------
67,725 730,544 25/10/2006 16:03:09
67,725 749,968 25/10/2006 16:04:11
67,725 0 25/10/2006 16:05:13
67,725 778,992 25/10/2006 16:06:10
67,725 41,560 25/10/2006 16:08:12
67,725 87,728 25/10/2006 16:09:13
67,725 0 25/10/2006 16:10:10
67,725 40 25/10/2006 16:11:14
67,725 0 25/10/2006 16:12:12
67,725 40 25/10/2006 16:13:11
67,725 0 25/10/2006 16:14:11
67,725 16 25/10/2006 16:15:12
67,725 0 25/10/2006 16:16:13
67,725 0 25/10/2006 16:17:10
67,725 0 25/10/2006 16:18:09
67,725 8 25/10/2006 16:19:12
67,725 0 25/10/2006 16:20:14
67,725 0 25/10/2006 16:21:12
67,725 40 25/10/2006 16:22:12
67,725 0 25/10/2006 16:23:11
67,725 0 25/10/2006 16:24:10

SID_SERIAL UNDO_KB CURRENT_TIME
---------- ------------ --------------------
67,725 0 25/10/2006 16:25:11
------------
sum 15,083,248

The USED_UBLK value have never gone more than 800MB. The sum of value of all the USED_UBLK is 15 Gig.

What would be going on in my UNDO tablespace. As I mentioned in previous question, the size of the entire schema is 2.5 Gig. I am wondering why 15 Gig of undo space so far. I guess it will fill up all the 33 Gig and eventually the program dies.

thanks,


Tom Kyte
October 25, 2006 - 4:23 pm UTC

if you have one transaction that started 5 days ago and has not committed - we cannot wrap around and reuse that space. Perhaps you have some really old uncommitted transactions (v$transaction can tell you how old they are)

cont...

A reader, October 25, 2006 - 5:34 pm UTC

there was nothing in v$transaction other than the one which I was executing.  Now my job failed because of ora-30036 and right now and this is what I have.

SQL> select count(*) from v$transaction;

  COUNT(*)
----------
         0

 

Tom Kyte
October 25, 2006 - 5:59 pm UTC

well, you only have 15 out of 32gig allocated, there is 17 more to go. Not sure what you are actually doing or what you are hitting when your job actually runs.

your extent analysis is wrong (you already exceeded 2gb, by a lot)
it doesn't matter how much undo is used right now, but rather what is used when you actually RUN

It would appear there is plenty of space, suggest you utilize support from this point.

set a rollback while importing

KK, December 22, 2006 - 5:35 am UTC

Tom,

when we are importing a huge dump file through "imp" utility ,how do we set a rollback segment for that import process (despite the option of making a huge rollback segment tablespace online )?

Tom Kyte
December 22, 2006 - 6:37 am UTC

why?

since import does inserts and inserts generate very little undo....


just use system managed undo - it'll steal extents as needed to make a rollback segment large enough.

Query most UNDO ever used?

Brian B, November 27, 2007 - 10:54 am UTC

We got an ORA-1555 during an 8-hour export process. Our undo retention is set to 4 hours, with automatic UNDO management. I know from this thread and others that this is our cause.

Before we increase undo_retention, I need to be able to predict whether increasing this will cause us to run out of allocated UNDO space, since increasing it will use more.

We have 1000MB allocated to the UNDO tablespace.
select sum(bytes)/1024/1024 from dba_tablespaces where tablespace_name='UNDOTBS2'; indicates we are using 30M of the 1000M allocated to the tablespace.

We are currently using 30M. Is there a way to tell whether this 30M is the most it has ever been?

My assumption: If 30M is all we ever use with a 4 hour retention then we could grow our undo retention many times over without allocating more space to the UNDO tablespace.


Knowing what the most UNDO ever used in the tablespace is will validate or invalidate my assumption.

Thanks for your advice.
Tom Kyte
November 27, 2007 - 3:57 pm UTC

v$undostat will be useful here. It is "not forever", but unless you've been snapshoting it yourself... it'll be the best you have.

Does RAC change anything?

Brian B, December 19, 2007 - 7:34 am UTC

In a RAC environment, does the undo_retention need to be the same on each node? Am I correct in understanding that each node manages its undo, so even though I run an export against a single node, rollback needed for that operation may be held on a different node, and therefore maybe subject to an earlier expiration if undo_retention is not the same on all nodes?
Tom Kyte
December 19, 2007 - 10:43 am UTC

for each parameter - we list RAC requirements

http://docs.oracle.com/docs/cd/B19306_01/server.102/b14237/initparams221.htm#sthref898

here it says we recommend they be the same...

because the odds of the ora-1555 are in proportion to the size of the SMALLEST undo stuff.

so, if one node has 5 minutes and another node has 50 minutes - effectively, the cluster has 5 minutes of undo...

because any query running on any node may need the undo from node 1 with 5 minutes of retained undo.

Re: RAC requirements

Brian B, December 19, 2007 - 12:37 pm UTC

*smacks head*

"If it were a snake...". I was even looking at that page of the doc earlier today - don't know how I missed it.

Thanks for confirming!


Undo log generation

DK, December 28, 2007 - 2:27 am UTC

Hi Tom,

In the PL/SQL proc I am doing like this.

Insert into t1 select *from t2....

and then

Update t1 set....

Note here that I am not commiting after the insert.

1)The question is that will it be faster if I commit after insert and then Update.Why?
2)How shall be the different components like Blocks,redo file undo file,etc be handled if I do not commit after Insert and try to Update the same table?

Thanks,
Dheeraj
Tom Kyte
December 28, 2007 - 3:42 pm UTC

it would be faster if you didn't update.

I don't see the point of the update, just select from T2 whatever you want to be the final answer, incorporate the update in the insert.


1) the more often you commit, the more undo, redo, and time you spend.
2) less efficiently

You commit at exactly one point in time: when your transaction is complete - not before, not after - at that point in time.

but you should not be doing a two step, you have a single sql statement

DK, December 31, 2007 - 1:58 am UTC

Thanks Tom,

Actually in between Insert and Update there is some processinsg happening the output of which is being used in the Update.So need to have seperate Insert and Update.

Ques: As I mentioned in point 2.I would like to ask the quesn again.I want to know when we do not commit after insert and try to update where is the data that was inserted lying.In other words where is the data processing during the update happening.As the data is still not written to the files.
What is the snapshot of the Redo,Undo etc at the point of time of update.

Please bear with my lack of knowledge on this.

Thanks,
Dheeraj
Tom Kyte
January 01, 2008 - 6:12 pm UTC

... I want to
know when we do not commit after insert and try to update where is the data
that was inserted lying ...


same place it would be existing if you did commit, no difference there.


Automatic UNDO Retention?

A reader, March 28, 2008 - 7:40 am UTC

Hi, Tom,

As stated in,
https://metalink.oracle.com/metalink/plsql/f?p=130:14:11380136665809356046::::p14_database_id,p14_docid,p14_show_header,p14_show_help,p14_black_frame,p14_font:NOT,461480.1,1,1,1,helvetica

They say...
"For fixed- size undo tablespaces, the system automatically tunes for the maximum possible undo retention period, based on undo tablespace size and usage history, and ignores UNDO_RETENTION unless retention guarantee is enabled. "

So... We don't have RETENTION GUARANTEE enable in our 10.2.0.3 instance, there's sufficient space in our fixed-size UNDO TBS to accomodate almost 4 hours of undo data, UNDO_RETENTION is set to 2hrs. However, in a 3,5 hours export with CONSISTENT=Y, we still got snapshot too old error...

I just wondering why this auto-tuning undo was not working. I was forced to modify our UNDO_RETENTION to 4 hours and as expected and what we do in earlier versions it worked.

Thanks a lot.
Ricardo Masashi.

Reader, June 04, 2009 - 6:07 pm UTC

I was creating an index and got the following error

ERROR at line 2:
ORA-01555: snapshot too old: rollback segment number 10 with name "_SYSSMU10$"
too small

DBA increased the UNDO_RETENTION

I started creating the index again and got the same error after 3 hours

ERROR at line 2:
ORA-01555: snapshot too old: rollback segment number 5 with name "_SYSSMU5$"
too small

DBA was told to decrease UNDO_RETENTION..

I thought it is the issue with UNDO tablespace size. Can you please explain what does this
snap shot too old error has to do with UNDO_RETENTION??

Tom Kyte
June 08, 2009 - 11:43 am UTC

did you search for ora-1555 on this site - so so so so much has been written about that.


Basically - we need a read consistent view of the data. The dba needs to

a) set undo_retention to a value LARGER than the amount of time your statement will take

and

b) MAKE SURE the undo tablespace has enough room to grow to HOLD that much undo.

But please - search around for 1555, it is well written about - a ton of material exists.

(I'm guessing you are doing an online index create or creating a text index...)

Reader, June 09, 2009 - 11:06 am UTC

Tom,
Thank you for your response.

I read about ORA-0155.
ORA-01555 error occurs when a DML is running and someone is querying the table on which the DML is running. There has to be enough space in undo to hold the before image data for the session which is querying the table.

Create index is a DDL and I did not understand why ORA-1555 error was encountered.
Can you please explain or point me to some link on your website where I can get this information?

tst table is daily partitioned on date. Table tst has 5 billion records and val is of type varchar2(10)

This is the script for index creation which is giving ORA-01555 error.

CREATE INDEX Index_01_tst
ON tst(val)
PCTFREE 1
LOCAL;

Tom Kyte
June 09, 2009 - 12:22 pm UTC

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:895410916429

DDL needs a consistent read, just as DML does - it uses the same consistent read mechanism. You can get an ORA-1555 on a read only tablespace (if you have sufficient transaction volume).

So, what I assume is happening is that you do have a rather high transaction volume.

Since you are creating a partitioned index - we can do something about it. We can create the index "unusable" and then rebuild each local index partition one at a time - instead of doing the entire thing in one fell swoop. This will also give you the ability to run lots of the rebuilds in parallel as well if you want.

see
http://docs.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_pclxut.htm#sthref4435

it describes how to create the index unusable and gives a method for a parallel rebuild on the local partitions if you desire.

Since each of the rebuilds will be small (as compared to the entire index) the likelihood of an ora-1555 is reduced and if it does happen - you will have lost less time due to the error.

Alexander, March 19, 2010 - 10:02 am UTC

Tom,

Is there anyway to use v$undostat to create a undo advice query to tell you based on the current workload, you can safely flashback N number of days?
Tom Kyte
March 19, 2010 - 12:03 pm UTC

no, not really.

All you can do is verify that you can flashback for your retention time (or not, if we had to prematurely expire some extents during your retention period).





Alexander, March 19, 2010 - 12:24 pm UTC

That's pretty close, I'd take that.

Got any sql for that, or a suggestion how to do it?
Tom Kyte
March 19, 2010 - 2:45 pm UTC

look at the unx* columns

http://docs.oracle.com/docs/cd/E11882_01/server.112/e10820/dynviews_3115.htm#REFRN30295

if you have them, we used unexpired blocks, meaning, you cannot be sure you can flashback to your retention period

but that is all it means.


If the last unx* stuff was longer than you retention period time ago - you can flash back to your retention period (at least, maybe more, maybe much much more)

If the last unx* stuff was nearer to "now" than your retention period, you cannot be sure of being able to flashback for your retention period - you will be able to flash back way long ago for some queries, to the flashback retention for others and maybe not more that 1 second ago for others.


So, all it can tell you is "retention period is OK" or "retention period might not be OK" to flashback to.

Multiple transaction block in SQL

A reader, March 24, 2010 - 12:47 am UTC

I want Multiple transaction blocks in the procedure

Following is the scenario

1. I want to validate the data and keep the log in error table
2. If any error occurs during processing (half done) procedure should rollback only the half processed data but not the error table


In my code

-- ERROR Check
INSERT INTO ERR_TAB;

FOR on Cursor.....
-- Check Error (Database Related validation)
INSERT INTO ERR_TAB;

-- In no error
INSERT INTO ACTUAL_TAB;
end loop;

Before for loop 2 Error inserted
5 records processed successfully
Error occur in 6th record

Now I want to Rollback only 5 Records

How do I do that.............








Tom Kyte
March 24, 2010 - 5:58 am UTC

probably you want to use a savepoint, but - unfortunately I cannot get the logic of your control flow there at all - I don't understand your psuedo code.

In general it would be:
for x in C
loop
    savepoint foo;
    begin
        do your work here....
    exception
        when whatever
             rollback to foo; -- rolls back to LAST issued savepoint
             insert into log table;
    end;
end loop;



you also have autonomous transactions - you could write an autonomous transaction that logs and commits your error messages - something like:
procedure log_error( p_error_msg in varchar2 )
as
   pragma autonomous_transaction;
begin
   insert into error_log(msg) values ( p_error_msg);
   commit;
end;


and call that - it'll commit the insert into error log AND NOTHING ELSE.


Multiple transaction block in SQL

Shashikant, March 24, 2010 - 12:47 am UTC

I want Multiple transaction blocks in the procedure

Following is the scenario

1. I want to validate the data and keep the log in error table
2. If any error occurs during processing (half done) procedure should rollback only the half processed data but not the error table


In my code

-- ERROR Check
INSERT INTO ERR_TAB;

FOR on Cursor.....
-- Check Error (Database Related validation)
INSERT INTO ERR_TAB;

-- In no error
INSERT INTO ACTUAL_TAB;
end loop;

Before for loop 2 Error inserted
5 records processed successfully
Error occur in 6th record

Now I want to Rollback only 5 Records

How do I do that.............








Undo retention and block

A reader, September 20, 2010 - 9:18 pm UTC

Hi Tom,

I have few queries regarding Undo:

1) We know that Undo data can be overwritten after spending its time in undo segment upto Undo_retention period. Now if we commit a change, then can the undo block be retained upto that particular period of undo_retention?
2) Undo blocks are maintained in buffer cache. Then how do it get into Undo tablespace? Is it by LRU algorithm?
3) Would a undo block be searched in Undo tablespace? But how can a query know that the block is in undo tablespace?

My queries might be bit childish, but since I am new to this part of world,so I think you will forgive me.
Tom Kyte
September 21, 2010 - 3:37 pm UTC

1) you answered your own question.

You wrote:

... We know that Undo data can be overwritten after spending its time in undo
segment upto Undo_retention period. ...

which answers:

... Now if we commit a change, then can the
undo block be retained upto that particular period of undo_retention?
....

The two things go together.

We attempt to maintain UNDO in the undo segments for as long as the undo retention period tells us to. If you set that to 2 hours say, then we will attempt to maintain undo that is generated for AT LEAST 2 hours in the undo tablespace. If we cannot - we might overwrite it prematurely - or if you set up the undo retention guarantee - we'll stop processing until you give us more space or lower the retention time.


2) the same way table blocks do - they are buffered in a cache until the cache fills up and we need more space and then we write them to disk.

The undo blocks are IN the undo tablespace as soon as they are generated - the blocks for the undo tablespace (like any other data tablespace) might be found in the cache or on disk.

3) when we look for any block - we look in the cache - then we look on disk if not in the cache. The block is always in the undo tablespace - it just might be cached or on disk.

Undo retention

A reader, September 23, 2010 - 10:29 pm UTC

Thanks Tom,

That means after committing the change the previous undo blocks will try to exist upto Undo retention period, but if space is required then it may be overwritten. Isn't it?
Now if space is required then also the undo blocks may be overwritten under Undo retention period for which commit was still not issued. And on querying that block we shall get a ORA-01555:snapshot too old error. Is this also correct?
Tom Kyte
September 27, 2010 - 10:05 am UTC

... That means after committing the change the previous undo blocks will try to exist upto Undo retention period, but if space is required then it may be overwritten. Isn't it? ...

yes, unless you set up a guaranteed undo retention policy

http://docs.oracle.com/docs/cd/E11882_01/server.112/e17120/undo002.htm#ADMIN11463


Now if space is required then also the undo blocks may be overwritten under Undo retention period for which commit was still not issued

No, that cannot happen - we need the undo until you commit in the event you want to rollback. You cannot overwrite undo that is protecting uncommitted changes...

Alexander, September 27, 2010 - 10:25 am UTC

Retention Guarantee? When did this happen? It's tempting to use for flashback, but also sounds dangerous.
Tom Kyte
September 27, 2010 - 12:18 pm UTC

10g gave us that.

http://docs.oracle.com/docs/cd/B14117_01/server.101/b10739/undo.htm#sthref1416
http://docs.oracle.com/docs/cd/B19306_01/server.102/b14231/undo.htm#sthref1482


it is as dangerous as archivelog mode is :)

You want data protection, you have to have given some thought to sizing things - yes.

Undo retention

A reader, September 27, 2010 - 11:14 am UTC

Hi Tom,

I am more concern about 9i only.
So as I understand that undo retention only makes only undo blocks expired for which commit is issued.
I thought its main cause of ORA-01555:snapshot too old error is while doing only the rollback of uncommitted change the related undo data couldn't be found since that undo data might have been overwritten by other undo blocks requiring space (undo tablespace is increased for that). So it is faced while doing rollback only. Isn't it?
Tom Kyte
September 27, 2010 - 12:32 pm UTC

I am more concern about 9i only.


Ok, but I have no idea who you are, or what version you are using. As far as I know, this is the very first time you are posting here "reader".

So as I understand that undo retention only makes only undo blocks expired for which commit is issued.


Not really. It is the laws that govern UNDO that dictate this. Whether you use manual or automatic undo management the fact is "undo will remain UNTIL the transaction that generates it completes with a commit or a rollback".

I thought its main cause of ORA-01555:snapshot too old error is while doing only the rollback of uncommitted change the related undo data couldn't be found since that undo data might have been overwritten by other undo blocks requiring space (undo tablespace is increased for that). So it is faced while doing rollback only. Isn't it?


big, huge, massive mis-conception on your part.

You get a 1555 during a SELECT (read).

You never get a 1555 during a rollback - never.


1555's happen when you are trying to READ data - we do this thing called "read coonsistency"

http://docs.oracle.com/docs/cd/E11882_01/server.112/e16508/consist.htm#CNCPT221

When you start your query - we make sure every block processed by that query is as of the same point in time. We use the undo to rollback changes FOR YOUR QUERY - and if the undo we need to rollback a change FOR YOUR QUERY (we are not rolling back the database, we are not undoing a transaction) does not exist - yu get a 1555.


undo retention and ora 01555

A reader, September 28, 2010 - 11:04 pm UTC

Hi Tom,

Thanks for saving my life at the right time. It seems I need some more readings alongside as I am just in my early ages. I read from your early posts that ORA 1555 error is caused due to below 2 reasons:

1) Read consistency: When a query starts at SCN 12000, then it searches the desired blocks. On its way if it finds the blocks with SCN equal to or below 12000 it will read, but when it comes across blocks with SCN > 12000 it will ignore it (if isolation level is set to read committed which is default) and it will finds it corresponding undo block to find the previous SCN block (say with SCN 11950). It will read it and thus will proceed. Now if that undo block with SCN 11950 is overwritten because of exceeding undo retention period or within that period for space requirement we shall face ORA 1555.

Am I correct? If yes then how the query will come to know that the data block whose SCN is > 12000 has kept its early image in which undo block (with SCN 11950)? Is it because that undo's transaction slot is written in the block's header along with its SCN?

2) Delayed block clean out: When a query starts and comes across a block whose data has been just modified (actually committed), it will see that the header of that block still showing "uncommitted" and corresponding undo data address including its transaction slot (say 5.3). Now it will try to search that undo data in order to find if the corresponding transaction slot (i.e. 5.3) is showing committed or uncommitted so that it can clean the header of that data block since committed. If the query couldn't find that undo block which seems to be overwritten then it will throw a ORA 1555 error. It may also happen if that transaction slot of that undo block (i.e. 5.3) is overwritten by some other transaction is circular fashion.

Am I correct here now?
Tom Kyte
September 29, 2010 - 8:44 am UTC

1) correct.

there is a transaction history in the block header, when your query encounters a block that was modified since your query began, it'll look at the transaction history to find the last change - roll it back - and see what it has. If that rolled back block is good for your query - it'll use it - else it'll read the transaction history (which itself was rolled back - so the history can be as large as it needs to be) and do it again, and again and so on - until either it runs out of undo that it can apply (ora-1555) or it finds the version of the block it can use.

2) ... hose data has been just modified ...
remove the word just. It could have been modified 5 years ago, or 5 milliseconds ago.

... f the query couldn't find that undo block which seems to be overwritten then it will throw a ORA 1555 error. ...

It might throw a 1555, if it knows for a fact that the transaction committed a long time ago - it can clean out the block without having at the undo - otherwise - the block could never get cleaned out!

snapshot too old

A reader, September 29, 2010 - 12:49 pm UTC

Hi Tom,

As we know that every block holds a time in the transaction table in its header at which it was last modified which in turn corresponds to a certain SCN.
Now for Read consistency, will the query started at Time T1 (during which SCN was 12000) matches with the time specified in the header of last committed desired blocks? And will the query then want to find that undo (previous data at T1- with SCN 11980) for those data blocks which were modified at time T1+ (SCN 12040) to maintain consistency?
Tom Kyte
September 29, 2010 - 1:16 pm UTC

we know that a block has a transaction id in the header, which in turn can be used to key into the undo segment to discover more information about the transaction.


as that query that started at time T1 reads blocks, it will look at the transaction information and use it (in some way, shape or form) to decide if the version of the block is it looking at is good for it. If it decides "nope, this block is too new", it will unwind through the rollback (undo) data - putting the block back the way it was - until it has the version it wants.



There, I just said what I just said before - I don't know how else to say it. That is what happens.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library