write consistency/read consistency

`I am trying to do an UPDATE in table_a based on the result of a query on
table_b. For example, update my order (in table_a) if there is inventory in
stock (in table_b). We can always do this using something along the lines
of:

UPDATE table_a
SET number_ordered = number_ordered+1
WHERE EXISTS (
  SELECT 'x'
  FROM table_a, table_b
  WHERE <condition to check table_b for inventory for my order>
                         )

This looks like it should be nice and consistent. Everything in one SQL
statement. But as has been pointed out to me, it isn't. 

Follow this timeline:
Session A blocks a record in table_a
Session B starts the update (time 1). It is blocked by session A
Session C updates table_b, changing the result of my nested query (time 2)
Session A commits/rollback (doesn't matter)
Session B finishes the update using the query result from time 1 which is no
longer valid (the inventory is actually gone)

This is a bit different from the 'write consisntency' case discussed by Tom
Kyte
http://tkyte.blogspot.com/2005/08/something-different-part-i-of-iii.html

In his example, the data changed by session C is in table_a, the table being
updated. In this case, the SELECT is read consistent to the point in time
when the query began. The update then does a current read on the returned
records prior to doing the update. If anything has changed, the statement
rolls back and begins again from a new point in time. In Tom's example, data
in table_a has changed. In my example, it hasn't.

Here, the query returns a result set based on table_a and table_b. However,
when table_b is modified, which would change the result set, this is never
noticed as the query is not rerun. The curent reads of the table_a remain
unchanged, and so the update completes when the lock is removed. 

Is the only way to do this to break the statement up into multiple pieces
and use SELECT FOR UPDATE? 

Henry

Other related posts: