Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 9 ■ REDO AND UNDO 329 manually managed undo, which will wrap around and reuse undo space as soon as it can. It is primarily for this reason, the support of the UNDO_RETENTION parameter, that I highly recommend automatic undo management whenever possible. That single parameter reduces the possibility of an ORA-01555 error greatly (when it is set appropriately!). When using manual undo management, it is also important to remember that the probability of an ORA-01555 error is dictated by the smallest rollback segment in your system, not the largest and not the average. Adding one “big” rollback segment will not make this problem go away. It only takes the smallest rollback segment to wrap around while a query is processing, and this query stands a chance of an ORA-01555 error. This is why I was a big fan of equi-sized rollback segments when using the legacy rollback segments. In this fashion, each rollback segment is both the smallest and the largest. This is also why I avoid using “optimally” sized rollback segments. If you shrink a rollback segment that was forced to grow, you are throwing away a lot of undo that may be needed right after that. It discards the oldest rollback data when it does this, minimizing the risk, but still the risk is there. I prefer to manually shrink rollback segments during off-peak times if at all. I am getting a little too deep into the DBA role at this point, so we’ll be moving on to the next case. It’s just important that you understand that the ORA-01555 error in this case is due to the system not being sized correctly for your workload. The only solution is to size correctly for your workload. It is not your fault, but it is your problem since you hit it. It is the same as if you run out of temporary space during a query. You either configure sufficient temporary space for the system, or you rewrite the queries so they use a plan that does not require temporary space. To demonstrate this effect, we can set up a small, but somewhat artificial test. We’ll create a very small undo tablespace with one session that will generate many small transactions, virtually assuring us that it will wrap around and reuse its allocated space many times— regardless of the UNDO_RETENTION setting, since we are not permitting the undo tablespace to grow. The session that uses this undo segment will be modifying a table, T. It will use a full scan of T and read it from “top” to “bottom.” In another session, we will execute a query that will read the table T via an index. In this fashion, it will read the table somewhat randomly: it will read row 1, then row 1,000, then row 500, then row 20,001, and so on. In this way, we will tend to visit blocks very randomly and perhaps many times during the processing of our query. The odds of getting an ORA-01555 error in this case are virtually 100 percent. So, in one session we start with the following: ops$tkyte@ORA10G> create undo tablespace undo_small 2 datafile size 2m 3 autoextend off 4 / Tablespace created. ops$tkyte@ORA10G> alter system set undo_tablespace = undo_small; System altered. Now, we’ll set up the table T used to query and modify. Note that we are ordering the data randomly in this table. The CREATE TABLE AS SELECT tends to put the rows in the blocks in the order it fetches them from the query. We’ll just scramble the rows up so they are not artificially sorted in any order, randomizing their distribution:
330 CHAPTER 9 ■ REDO AND UNDO ops$tkyte@ORA10G> create table t 2 as 3 select * 4 from all_objects 5 order by dbms_random.random; Table created. ops$tkyte@ORA10G> alter table t add constraint t_pk primary key(object_id) 2 / Table altered. ops$tkyte@ORA10G> exec dbms_stats.gather_table_stats( user, 'T', cascade=> true ); PL/SQL procedure successfully completed. And now we are ready to do our modifications: ops$tkyte@ORA10G> begin 2 for x in ( select rowid rid from t ) 3 loop 4 update t set object_name = lower(object_name) where rowid = x.rid; 5 commit; 6 end loop; 7 end; 8 / Now, while that is running, we run a query in another session. This query was reading this table T and processing each record. I spent about 1/100 of a second processing each record before fetching the next (simulated using DBMS_LOCK.SLEEP(0.01)). I used the FIRST_ROWS hint in the query to have it use the index we created to read the rows out of the table via the index sorted by OBJECT_ID. Since the data was randomly inserted into the table, we would tend to query blocks in the table rather randomly. This block ran for only a couple of seconds before failing: ops$tkyte@ORA10G> declare 2 cursor c is 3 select /*+ first_rows */ object_name 4 from t 5 order by object_id; 6 7 l_object_name t.object_name%type; 8 l_rowcnt number := 0; 9 begin 10 open c; 11 loop 12 fetch c into l_object_name; 13 exit when c%notfound; 14 dbms_lock.sleep( 0.01 ); 15 l_rowcnt := l_rowcnt+1; 16 end loop;
- Page 324 and 325: CHAPTER 8 ■ TRANSACTIONS 279 5 pr
- Page 326: CHAPTER 8 ■ TRANSACTIONS 281 scot
- Page 329 and 330: 284 CHAPTER 9 ■ REDO AND UNDO cri
- Page 331 and 332: 286 CHAPTER 9 ■ REDO AND UNDO Fir
- Page 333 and 334: 288 CHAPTER 9 ■ REDO AND UNDO The
- Page 335 and 336: 290 CHAPTER 9 ■ REDO AND UNDO We
- Page 337 and 338: 292 CHAPTER 9 ■ REDO AND UNDO Wha
- Page 339 and 340: 294 CHAPTER 9 ■ REDO AND UNDO row
- Page 341 and 342: 296 CHAPTER 9 ■ REDO AND UNDO If
- Page 343 and 344: 298 CHAPTER 9 ■ REDO AND UNDO ops
- Page 345 and 346: 300 CHAPTER 9 ■ REDO AND UNDO Inv
- Page 347 and 348: 302 CHAPTER 9 ■ REDO AND UNDO The
- Page 349 and 350: 304 CHAPTER 9 ■ REDO AND UNDO 41
- Page 351 and 352: 306 CHAPTER 9 ■ REDO AND UNDO ins
- Page 353 and 354: 308 CHAPTER 9 ■ REDO AND UNDO So,
- Page 355 and 356: 310 CHAPTER 9 ■ REDO AND UNDO ops
- Page 357 and 358: 312 CHAPTER 9 ■ REDO AND UNDO ops
- Page 359 and 360: 314 CHAPTER 9 ■ REDO AND UNDO •
- Page 361 and 362: 316 CHAPTER 9 ■ REDO AND UNDO ...
- Page 363 and 364: 318 CHAPTER 9 ■ REDO AND UNDO •
- Page 365 and 366: 320 CHAPTER 9 ■ REDO AND UNDO bac
- Page 367 and 368: 322 CHAPTER 9 ■ REDO AND UNDO As
- Page 369 and 370: 324 CHAPTER 9 ■ REDO AND UNDO ops
- Page 371 and 372: 326 CHAPTER 9 ■ REDO AND UNDO wil
- Page 373: 328 CHAPTER 9 ■ REDO AND UNDO Thi
- Page 377 and 378: 332 CHAPTER 9 ■ REDO AND UNDO Whe
- Page 379 and 380: 334 CHAPTER 9 ■ REDO AND UNDO Tha
- Page 381 and 382: 336 CHAPTER 9 ■ REDO AND UNDO tou
- Page 383 and 384: 338 CHAPTER 10 ■ DATABASE TABLES
- Page 385 and 386: 340 CHAPTER 10 ■ DATABASE TABLES
- Page 387 and 388: 342 CHAPTER 10 ■ DATABASE TABLES
- Page 389 and 390: 344 CHAPTER 10 ■ DATABASE TABLES
- Page 391 and 392: 346 CHAPTER 10 ■ DATABASE TABLES
- Page 393 and 394: 348 CHAPTER 10 ■ DATABASE TABLES
- Page 395 and 396: 350 CHAPTER 10 ■ DATABASE TABLES
- Page 397 and 398: 352 CHAPTER 10 ■ DATABASE TABLES
- Page 399 and 400: 354 CHAPTER 10 ■ DATABASE TABLES
- Page 401 and 402: 356 CHAPTER 10 ■ DATABASE TABLES
- Page 403 and 404: 358 CHAPTER 10 ■ DATABASE TABLES
- Page 405 and 406: 360 CHAPTER 10 ■ DATABASE TABLES
- Page 407 and 408: 362 CHAPTER 10 ■ DATABASE TABLES
- Page 409 and 410: 364 CHAPTER 10 ■ DATABASE TABLES
- Page 411 and 412: 366 CHAPTER 10 ■ DATABASE TABLES
- Page 413 and 414: 368 CHAPTER 10 ■ DATABASE TABLES
- Page 415 and 416: 370 CHAPTER 10 ■ DATABASE TABLES
- Page 417 and 418: 372 CHAPTER 10 ■ DATABASE TABLES
- Page 419 and 420: 374 CHAPTER 10 ■ DATABASE TABLES
- Page 421 and 422: 376 CHAPTER 10 ■ DATABASE TABLES
- Page 423 and 424: 378 CHAPTER 10 ■ DATABASE TABLES
CHAPTER 9 ■ REDO AND UNDO 329<br />
manually managed undo, which will wrap around <strong>and</strong> reuse undo space as soon as it can. It is<br />
primarily for this reason, the support of the UNDO_RETENTION parameter, that I highly recommend<br />
automatic undo management whenever possible. That single parameter reduces the<br />
possibility of an ORA-01555 error greatly (when it is set appropriately!).<br />
When using manual undo management, it is also important to remember that the probability<br />
of an ORA-01555 error is dictated by the smallest rollback segment in your system, not the<br />
largest <strong>and</strong> not the average. Adding one “big” rollback segment will not make this problem go<br />
away. It only takes the smallest rollback segment to wrap around while a query is processing,<br />
<strong>and</strong> this query st<strong>and</strong>s a chance of an ORA-01555 error. This is why I was a big fan of equi-sized<br />
rollback segments when using the legacy rollback segments. In this fashion, each rollback<br />
segment is both the smallest <strong>and</strong> the largest. This is also why I avoid using “optimally” sized<br />
rollback segments. If you shrink a rollback segment that was forced to grow, you are throwing<br />
away a lot of undo that may be needed right after that. It discards the oldest rollback data<br />
when it does this, minimizing the risk, but still the risk is there. I prefer to manually shrink<br />
rollback segments during off-peak times if at all.<br />
I am getting a little too deep into the DBA role at this point, so we’ll be moving on to the<br />
next case. It’s just important that you underst<strong>and</strong> that the ORA-01555 error in this case is due to<br />
the system not being sized correctly for your workload. The only solution is to size correctly<br />
for your workload. It is not your fault, but it is your problem since you hit it. It is the same as<br />
if you run out of temporary space during a query. You either configure sufficient temporary<br />
space for the system, or you rewrite the queries so they use a plan that does not require temporary<br />
space.<br />
To demonstrate this effect, we can set up a small, but somewhat artificial test. We’ll create<br />
a very small undo tablespace with one session that will generate many small transactions,<br />
virtually assuring us that it will wrap around <strong>and</strong> reuse its allocated space many times—<br />
regardless of the UNDO_RETENTION setting, since we are not permitting the undo tablespace to<br />
grow. The session that uses this undo segment will be modifying a table, T. It will use a full<br />
scan of T <strong>and</strong> read it from “top” to “bottom.” In another session, we will execute a query that<br />
will read the table T via an index. In this fashion, it will read the table somewhat r<strong>and</strong>omly:<br />
it will read row 1, then row 1,000, then row 500, then row 20,001, <strong>and</strong> so on. In this way, we<br />
will tend to visit blocks very r<strong>and</strong>omly <strong>and</strong> perhaps many times during the processing of our<br />
query. The odds of getting an ORA-01555 error in this case are virtually 100 percent. So, in one<br />
session we start with the following:<br />
ops$tkyte@ORA10G> create undo tablespace undo_small<br />
2 datafile size 2m<br />
3 autoextend off<br />
4 /<br />
Tablespace created.<br />
ops$tkyte@ORA10G> alter system set undo_tablespace = undo_small;<br />
System altered.<br />
Now, we’ll set up the table T used to query <strong>and</strong> modify. Note that we are ordering the data<br />
r<strong>and</strong>omly in this table. The CREATE TABLE AS SELECT tends to put the rows in the blocks in the<br />
order it fetches them from the query. We’ll just scramble the rows up so they are not artificially<br />
sorted in any order, r<strong>and</strong>omizing their distribution: