Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 7 ■ CONCURRENCY AND MULTI-VERSIONING 253 • Consider a trigger that maintains some PL/SQL global variables, such as the number of rows processed. When a statement that restarts rolls back, the modifications to PL/SQL variables won’t “roll back.” • Virtually any function that starts with UTL_ (UTL_FILE, UTL_HTTP, UTL_SMTP, and so on) should be considered susceptible to a statement restart. When the statement restarts, UTL_FILE won’t “un-write” to the file it was writing to. • Any trigger that is part of an autonomous transaction must be suspect. When the statement restarts and rolls back, the autonomous transaction cannot be rolled back. All of these consequences must be handled with care in the belief that they may be fired more than once per row or be fired for a row that won’t be updated by the statement after all. The second reason you should care about potential restarts is performance related. We have been using a single-row example, but what happens if you start a large batch update and it is restarted after processing the first 100,000 records? It will roll back the 100,000 row changes, restart in SELECT FOR UPDATE mode, and do the 100,000 row changes again after that. You might notice, after putting in that simple audit trail trigger (the one that reads the :NEW and :OLD values), that performance is much worse than you can explain, even though nothing else has changed except the new triggers. It could be that you are restarting queries you never used to in the past. Or the addition of a tiny program that updates just a single row here and there makes a batch process that used to run in an hour suddenly run in many hours due to restarts that never used to take place. This is not a new feature of Oracle—it has been in the database since version 4.0, when read consistency was introduced. I myself was not totally aware of how it worked until the summer of 2003 and, after I discovered what it implied, I was able to answer a lot of “How could that have happened?” questions from my own past. It has made me swear off using autonomous transactions in triggers almost entirely, and it has made me rethink the way some of my applications have been implemented. For example, I’ll never send e-mail from a trigger directly; rather, I’ll always use DBMS_JOB or the new Oracle 10g scheduler facility to send the e-mail after my transaction commits. This makes the sending of the e-mail “transactional”—that is, if the statement that caused the trigger to fire and send the e-mail is restarted, the rollback it performs will roll back the DBMS_JOB request. Most everything nontransactional that I did in triggers was modified to be done in a job after the fact, making it all transactionally consistent. Summary In this chapter, we covered a lot of material that, at times, likely made you scratch your head. However, it is vital that you understand these issues. For example, if you were not aware of the statement-level restart, you might not be able to figure out how a certain set of circumstances could have taken place. That is, you would not be able to explain some of the daily empirical observations you make. In fact, if you were not aware of the restarts, you might wrongly suspect the actual fault to be due to the circumstances or an end user error. It would be one of those unreproducible issues, as it takes many things happening in a specific order to observe.
254 CHAPTER 7 ■ CONCURRENCY AND MULTI-VERSIONING We took a look at the meaning of the isolation levels set out in the SQL standard and at how Oracle implements them, and at times we contrasted Oracle’s implementation with that of other databases. We saw that in other implementations (i.e., ones that employ read locks to provide consistent data), there is a huge trade-off between concurrency and consistency. To get highly concurrent access to data, you would have to decrease your need for consistent answers. To get consistent, correct answers, you would need to live with decreased concurrency. We saw how in Oracle that is not the case, due to its multi-versioning feature. Table 7-9 sums up what you might expect in a database that employs read locking versus Oracle’s multi-versioning. Table 7-9. A Comparison of Transaction, Concurrency, and Locking Behavior in Oracle vs. Databases That Employ Read Locking Writes Reads Deadlock- Incorrect Lock Block Block Sensitive Query Lost Escalation Isolation Level Implementation Reads Writes Reads Results Updates or Limits READ UNCOMMITTED Not Oracle No No No Yes Yes Yes READ COMMITTED Not Oracle Yes No No Yes Yes Yes READ COMMITTED Oracle No No No No No* No REPEATABLE READ Not Oracle Yes Yes Yes No No Yes SERIALIZABLE Not Oracle Yes Yes Yes No No Yes SERIALIZABLE Oracle No No No No No No * With SELECT FOR UPDATE NOWAIT. Concurrency controls and how the database implements them are definitely things you want to have a good grasp of. I’ve been singing the praises of multi-versioning and read consistency, but like everything else in the world, they are double-edged swords. If you don’t understand that multi-versioning is there and how it works, you will make errors in application design. Consider the resource scheduler example from Chapter 1. In a database without multi-versioning and its associated non-blocking reads, the original logic employed by the program may very well have worked. However, this logic would fall apart when implemented in Oracle—it would allow data integrity to be compromised. Unless you know how it works, you will write programs that corrupt data. It is that simple.
- Page 248 and 249: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 250 and 251: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 252 and 253: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 254 and 255: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 256 and 257: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 258 and 259: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 260 and 261: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 262 and 263: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 264 and 265: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 266 and 267: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 268 and 269: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 270 and 271: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 272 and 273: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 274 and 275: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 276 and 277: CHAPTER 7 ■ ■ ■ Concurrency a
- Page 278 and 279: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 280 and 281: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 282 and 283: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 284 and 285: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 286 and 287: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 288 and 289: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 290 and 291: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 292 and 293: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 294 and 295: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 296 and 297: 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 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
254<br />
CHAPTER 7 ■ CONCURRENCY AND MULTI-VERSIONING<br />
We took a look at the meaning of the isolation levels set out in the SQL st<strong>and</strong>ard <strong>and</strong> at<br />
how <strong>Oracle</strong> implements them, <strong>and</strong> at times we contrasted <strong>Oracle</strong>’s implementation with that<br />
of other databases. We saw that in other implementations (i.e., ones that employ read locks to<br />
provide consistent data), there is a huge trade-off between concurrency <strong>and</strong> consistency. To<br />
get highly concurrent access to data, you would have to decrease your need for consistent<br />
answers. To get consistent, correct answers, you would need to live with decreased concurrency.<br />
We saw how in <strong>Oracle</strong> that is not the case, due to its multi-versioning feature.<br />
Table 7-9 sums up what you might expect in a database that employs read locking versus<br />
<strong>Oracle</strong>’s multi-versioning.<br />
Table 7-9. A Comparison of Transaction, Concurrency, <strong>and</strong> Locking Behavior in <strong>Oracle</strong> vs. <strong>Database</strong>s That<br />
Employ Read Locking<br />
Writes Reads Deadlock- Incorrect Lock<br />
Block Block Sensitive Query Lost Escalation<br />
Isolation Level Implementation Reads Writes Reads Results Updates or Limits<br />
READ UNCOMMITTED Not <strong>Oracle</strong> No No No Yes Yes Yes<br />
READ COMMITTED Not <strong>Oracle</strong> Yes No No Yes Yes Yes<br />
READ COMMITTED <strong>Oracle</strong> No No No No No* No<br />
REPEATABLE READ Not <strong>Oracle</strong> Yes Yes Yes No No Yes<br />
SERIALIZABLE Not <strong>Oracle</strong> Yes Yes Yes No No Yes<br />
SERIALIZABLE <strong>Oracle</strong> No No No No No No<br />
* With SELECT FOR UPDATE NOWAIT.<br />
Concurrency controls <strong>and</strong> how the database implements them are definitely things you<br />
want to have a good grasp of. I’ve been singing the praises of multi-versioning <strong>and</strong> read consistency,<br />
but like everything else in the world, they are double-edged swords. If you don’t<br />
underst<strong>and</strong> that multi-versioning is there <strong>and</strong> how it works, you will make errors in application<br />
design. Consider the resource scheduler example from Chapter 1. In a database without<br />
multi-versioning <strong>and</strong> its associated non-blocking reads, the original logic employed by the<br />
program may very well have worked. However, this logic would fall apart when implemented<br />
in <strong>Oracle</strong>—it would allow data integrity to be compromised. Unless you know how it works,<br />
you will write programs that corrupt data. It is that simple.