A database will automatically figure out how to process two or more transactions in parallel (as serializable schedules) by overcoming the read-write conflicts (using locking). By default there will be isolation among them.
So why do we still need to lock any data in the database by using statements like SELECT FOR UPDATE? Why can't we proceed with whatever we want in a transaction block?
Begin transaction
//queries
//commit
End transaction
why we can't proceed with whatever we want in a transaction block?
Because in Oracle, readers don't block writers. If you select from a table you don't lock it and there is no transaction. So, imagine you do:
select col1, col2 into l_col1, l_col2
from table1
where ...;
if (<some logic based on l_col2>) then
update table1 set col2 = something where col1 = l_col1;
end if;
That's fine; but if two sessions run that code at the same time, one session could update the row between the other session selecting and performing its update - causing a lost update, or incorrect logic as the state wasn't actually as expected.
If instead you do select ... for update:
select col1, col2 into l_col1, l_col2
from table
where ...
for update; -- or: for update of col2
if (<some logic based on l_col2>) then
update table1 set col2 = something where col1 = l_col1;
end if;
then the row selected from the table is locked by the first session when it does select for update, so a second session has to wait for that transaction to complete before it can obtain the lock, and it will see the state of the row after the first update has applied. No lost update, no confusion.
You can also lock rows you don't want to update, as the documentation says:
The
SELECTstatement with theFOR UPDATEclause (SELECT FOR UPDATEstatement) selects the rows of the result set and locks them.SELECT FOR UPDATElets you base an update on the existing values in the rows, because it ensures that no other user can change those values before you update them. You can also useSELECT FOR UPDATEto lock rows that you do not want to update, as in Example 9-6.
And you can tweak the behaviour:
By default, the
SELECT FOR UPDATEstatement waits until the requested row lock is acquired. To change this behavior, use theNOWAIT,WAIT, orSKIP LOCKEDclause of theSELECT FOR UPDATEstatement. For information about these clauses, see Oracle Database SQL Language Reference.
If the select for update is in a cursor loop then it also allows you to do
update table1 set col2 = something where current of <cursor>;
When
SELECT FOR UPDATEis associated with an explicit cursor, the cursor is called aFOR UPDATEcursor. Only aFOR UPDATEcursor can appear in theCURRENTOF clause of anUPDATEorDELETEstatement. (TheCURRENT OFclause, a PL/SQL extension to theWHEREclause of the SQL statementsUPDATEandDELETE, restricts the statement to the current row of the cursor.)
Rows selected by the cursor query are locked as they are fetched. (But the table itself isn't locked.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With