05.11.2015 Views

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

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

CHAPTER 7 ■ CONCURRENCY AND MULTI-VERSIONING 249<br />

Table 7-8. Sequence of Updates<br />

Time Session 1 Session 2 Comment<br />

T1 Update t This updates the one row that matches the<br />

set y = 10<br />

criteria.<br />

where y = 5;<br />

T2 Update t Using consistent reads, this will find the<br />

Set x = x+1 record session 1 modified, but it won’t be<br />

Where y = 5; able to update it since session 1 has it blocked.<br />

Session 2 will block <strong>and</strong> wait for this row.<br />

T3 Commit; This releases session 1; session 1 becomes<br />

unblocked. It can finally do the current read<br />

on the block containing this row, where Y was<br />

equal to 5 when session 1 began its update.<br />

So the record that was Y=5 when you began the UPDATE is no longer Y=5. The consistent<br />

read component of the UPDATE says, “You want to update this record because Y was 5 when we<br />

began,” but the current version of the block makes you think, “Oh, no, I cannot update this<br />

row because Y isn’t 5 anymore—it would be wrong.”<br />

If we just skipped this record at this point <strong>and</strong> ignored it, then we would have a nondeterministic<br />

update. It would be throwing data consistency <strong>and</strong> integrity out the window. The<br />

outcome of the update (how many <strong>and</strong> which rows were modified) would depend on the<br />

order in which rows got hit in the table <strong>and</strong> what other activity just happened to be going on.<br />

You could take the same exact set of rows <strong>and</strong> in two different databases, each one running<br />

the transactions in exactly the same mix, you could observe different results, just because the<br />

rows were in different places on the disk.<br />

In this case, <strong>Oracle</strong> chose to restart the update. When the row that was Y=5 when you<br />

started is found to contain the value Y=10, <strong>Oracle</strong> will silently roll back your update <strong>and</strong> restart<br />

it—assuming you are using READ COMMITTED isolation. If you are using SERIALIZABLE isolation,<br />

then at this point you would receive an ORA-08177: can't serialize access error for this<br />

transaction. In READ COMMITTED mode, after the transaction rolls back your update, the database<br />

will restart the update (i.e., change the point in time at which the update is “as of”), <strong>and</strong><br />

instead of updating the data again, it will go into SELECT FOR UPDATE mode <strong>and</strong> attempt to lock<br />

all of the rows WHERE Y=5 for your session. Once it does this, it will run the UPDATE against that<br />

locked set of data, thus ensuring this time that it can complete without restarting.<br />

But to continue on with the “but what happens . . .” train of thought, what happens if<br />

after restarting the update <strong>and</strong> going into SELECT FOR UPDATE mode (which has the same readconsistent<br />

<strong>and</strong> read current block gets going on as an update does), a row that was Y=5 when<br />

you started the SELECT FOR UPDATE is found to be Y=11 when you go to get the current version<br />

of it? That SELECT FOR UDPDATE will restart <strong>and</strong> the cycle begins again.<br />

There are two questions to be addressed here—two questions that interested me, anyway.<br />

The first is, Can we observe this? Can we see this actually happen? And the second is, So what?<br />

What does this actually mean to us as developers? We’ll address these questions in turn now.<br />

Seeing a Restart<br />

It is easier to see a restart than you might at first think. We’ll be able to observe one, in fact,<br />

using a simple one-row table. This is the table we’ll use to test with:

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

Saved successfully!

Ooh no, something went wrong!