Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 9 ■ REDO AND UNDO 299 Table 9-2. Time to ROLLBACK by Transaction Size Rows Inserted Rollback Time Commit Time (Seconds) (Seconds) 10 0.04 0.06 100 0.05 0.04 1,000 0.06 0.06 10,000 0.22 0.06 100,000 1.46 0.07 This is to be expected, as a ROLLBACK has to physically undo the work we’ve done. Similar to a COMMIT, a series of operations must be performed. Before we even get to the ROLLBACK, the database has already done a lot of work. To recap, the following would have happened: • Undo segment records have been generated in the SGA. • Modified data blocks have been generated in the SGA. • A buffered redo log for the preceding two items has been generated in the SGA. • Depending on the size of the preceding three items, and the amount of time spent, some combination of the previous data may be flushed onto disk already. • All locks have been acquired. When we ROLLBACK, • We undo all of the changes made. This is accomplished by reading the data back from the undo segment, and in effect, reversing our operation and then marking the undo entry as applied. If we inserted a row, a ROLLBACK will delete it. If we updated a row, a rollback will reverse the update. If we deleted a row, a rollback will re-insert it again. • All locks held by our session are released, and everyone who was enqueued waiting on locks we held will be released. A COMMIT, on the other hand, just flushes any remaining data in the redo log buffers. It does very little work compared to a ROLLBACK. The point here is that you don’t want to roll back unless you have to. It is expensive since you spend a lot of time doing the work, and you’ll also spend a lot of time undoing the work. Don’t do work unless you’re sure you are going to want to COMMIT it. This sounds like common sense—of course I wouldn’t do all of the work unless I wanted to COMMIT it. Many times, however, I’ve seen a situation where a developer will use a “real” table as a temporary table, fill it up with data, report on it, and then roll back to get rid of the temporary data. In the next section, we’ll talk about true temporary tables and how to avoid this issue.
300 CHAPTER 9 ■ REDO AND UNDO Investigating Redo As a developer, it’s often important to be able to measure how much redo your operations generate. The more redo you generate, the longer your operations will take, and the slower the entire system will be. You are not just affecting your session, but every session. Redo management is a point of serialization within the database. There is just one LGWR in any Oracle instance, and eventually all transactions end up at LGWR, asking it to manage their redo and COMMIT their transaction. The more it has to do, the slower the system will be. By seeing how much redo an operation tends to generate, and testing more than one approach to a problem, you can find the best way to do things. Measuring Redo It is pretty straightforward to see how much redo is being generated, as shown earlier in the chapter. I used the AUTOTRACE built-in feature of SQL*Plus. But AUTOTRACE works only with simple DML—it cannot, for example, be used to view what a stored procedure call did. For that, we’ll need access to two dynamic performance views: • V$MYSTAT, which has just our session’s statistics in it • V$STATNAME, which tells us what each row in V$MYSTAT represents (the name of the statistic we are looking at) I do these sorts of measurements so often that I use two scripts I call mystat and mystat2. The mystat.sql script saves the beginning value of the statistic I’m interested in, such as redo size, in a SQL*Plus variable: set verify off column value new_val V define S="&1" set autotrace off select a.name, b.value from v$statname a, v$mystat b where a.statistic# = b.statistic# and lower(a.name) like '%' || lower('&S')||'%' / The mystat2.sql script simply prints out the difference between the beginning value and the end value of that statistic: set verify off select a.name, b.value V, to_char(b.value-&V,'999,999,999,999') diff from v$statname a, v$mystat b where a.statistic# = b.statistic# and lower(a.name) like '%' || lower('&S')||'%' / Now we’re ready to measure how much redo a given transaction would generate. All we need to do is this:
- Page 294 and 295: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 296 and 297: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 298 and 299: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 300 and 301: CHAPTER 8 ■ ■ ■ Transactions
- Page 302 and 303: CHAPTER 8 ■ TRANSACTIONS 257 •
- Page 304 and 305: CHAPTER 8 ■ TRANSACTIONS 259 So,
- Page 306 and 307: CHAPTER 8 ■ TRANSACTIONS 261 X --
- Page 308 and 309: CHAPTER 8 ■ TRANSACTIONS 263 “s
- Page 310 and 311: CHAPTER 8 ■ TRANSACTIONS 265 busi
- Page 312 and 313: CHAPTER 8 ■ TRANSACTIONS 267 Many
- Page 314 and 315: CHAPTER 8 ■ TRANSACTIONS 269 ops$
- Page 316 and 317: CHAPTER 8 ■ TRANSACTIONS 271 last
- Page 318 and 319: CHAPTER 8 ■ TRANSACTIONS 273 Dist
- Page 320 and 321: CHAPTER 8 ■ TRANSACTIONS 275 Auto
- Page 322 and 323: CHAPTER 8 ■ TRANSACTIONS 277 3 Au
- 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: 298 CHAPTER 9 ■ REDO AND UNDO ops
- 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 and 374: 328 CHAPTER 9 ■ REDO AND UNDO Thi
- Page 375 and 376: 330 CHAPTER 9 ■ REDO AND UNDO ops
- 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
CHAPTER 9 ■ REDO AND UNDO 299<br />
Table 9-2. Time to ROLLBACK by Transaction Size<br />
Rows Inserted Rollback Time Commit Time<br />
(Seconds) (Seconds)<br />
10 0.04 0.06<br />
100 0.05 0.04<br />
1,000 0.06 0.06<br />
10,000 0.22 0.06<br />
100,000 1.46 0.07<br />
This is to be expected, as a ROLLBACK has to physically undo the work we’ve done. Similar<br />
to a COMMIT, a series of operations must be performed. Before we even get to the ROLLBACK, the<br />
database has already done a lot of work. To recap, the following would have happened:<br />
• Undo segment records have been generated in the SGA.<br />
• Modified data blocks have been generated in the SGA.<br />
• A buffered redo log for the preceding two items has been generated in the SGA.<br />
• Depending on the size of the preceding three items, <strong>and</strong> the amount of time spent,<br />
some combination of the previous data may be flushed onto disk already.<br />
• All locks have been acquired.<br />
When we ROLLBACK,<br />
• We undo all of the changes made. This is accomplished by reading the data back from<br />
the undo segment, <strong>and</strong> in effect, reversing our operation <strong>and</strong> then marking the undo<br />
entry as applied. If we inserted a row, a ROLLBACK will delete it. If we updated a row, a<br />
rollback will reverse the update. If we deleted a row, a rollback will re-insert it again.<br />
• All locks held by our session are released, <strong>and</strong> everyone who was enqueued waiting on<br />
locks we held will be released.<br />
A COMMIT, on the other h<strong>and</strong>, just flushes any remaining data in the redo log buffers. It<br />
does very little work compared to a ROLLBACK. The point here is that you don’t want to roll back<br />
unless you have to. It is expensive since you spend a lot of time doing the work, <strong>and</strong> you’ll also<br />
spend a lot of time undoing the work. Don’t do work unless you’re sure you are going to want<br />
to COMMIT it. This sounds like common sense—of course I wouldn’t do all of the work unless I<br />
wanted to COMMIT it. Many times, however, I’ve seen a situation where a developer will use a<br />
“real” table as a temporary table, fill it up with data, report on it, <strong>and</strong> then roll back to get rid<br />
of the temporary data. In the next section, we’ll talk about true temporary tables <strong>and</strong> how to<br />
avoid this issue.