Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
![]() |
![]() |
Home -> Community -> Mailing Lists -> Oracle-L -> RE: write consistency/read consistency
Hi,
If a block of code should be atomic, i.e. it has to be run by only one concurrent session in order not to break your data consistency, you can wrap it in a user-defined lock block using DBMS_LOCK package as seen below;
dbms_lock.allocate_unique('my_lock', v_lock_handle) ; if dbms_lock.request(v_lock_handle, release_on_commit => true) != 0 then
rollback ;
raise e_cant_acquire_lock ;
end if ;
// Your code here
commit ;
Best regards.
Ogün Heper
From: oracle-l-bounce_at_freelists.org [mailto:oracle-l-bounce_at_freelists.org] On Behalf Of Henry Poras
Sent: Monday, June 26, 2006 8:02 PM
To: oracle-l_at_freelists.org
Subject: 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 <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
-- http://www.freelists.org/webpage/oracle-lReceived on Tue Jun 27 2006 - 03:03:22 CDT
![]() |
![]() |