Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

rekharaghuram
from rekharaghuram More from this publisher
05.11.2015 Views

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.

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.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!