Optimistic Locking With Concurrency - PLSQL
Optimistic Locking With Concurrency - PLSQL
Agenda
Handling Concurrency
a) Database
Pessimistic Locking
Optimistic Locking
Optimistic Locking with Concurrency
b) Application
Incompatibility
Conflict Domain
Concurrency
Concurrency is the ability of a database to allow multiple users to affect multiple
transactions. One of the key functions of a database is to ensure that multiple users
can read and write to the database without overwriting each other's changes
inadvertently or reading inconsistent data due to in-progress changes.
Several problems can occur when concurrent transactions execute in an
uncontrolledmanner. Some Concurrency Problems in transaction are: Dirty Read and
Lost Update
There are two main kinds of concurrency control mechanisms:
Pessimistic Locking
Optimistic Locking
Pessimistic Locking
Apply explicit lock in advance, before updating.
This is achieved using SELECTFOR UPDATE clause. Lock will be release, once
transaction control statement executed.
Other user will be forced to wait until the first transaction has completed, which has locked
explicitly.
Even though this is very simple and safe, this approach has two major problems....
Lockout - An application user selects a record for update, and then leaves without
finishing or aborting the transaction. All other users that need to update that record are
forced to wait until the user returns and completes the transaction, or until the DBA kills the
offending transaction and releases the lock.
Deadlock - Users A and B are both updating the database at the same time. User A locks
a record and then attempt to acquire a lock held by user B - who is waiting to obtain a lock
held by user A. Both transactions go into an infinite wait state - the so-called deadly embrace
or deadlock.
Optimistic Locking
Optimistic locking offers an elegant solution to the problems outlined above. Optimistic locking
does not lock records when they are read, and proceeds on the assumption that the data being
updated has not changed since the read. Since no locks are taken out during the read, it doesnt
matter if the user goes to pause mode after starting a transaction, and deadlocks are all but
eliminated since users should never have to wait on each others locks.
The Oracle database uses optimistic locking by default. Any command that begins with UPDATE
SET that is not preceded by a SELECTFOR UPDATE is an example of optimistic locking.
However, optimistic locking does not provide concurrency control. Concurrency control is the
mechanism that ensures that the data being written back to the database is consistent with what
was read from the database in the first place - that is no other transaction has updated the data
after it was read.
Ideally we need a method of allowing optimistic locking while ensuring concurrency.
Implementation Strategy
The concurrency should always be enforced at the trigger level.
Using an integer for the concurrency key makes interactive SQL much simpler, and if combined
with the get_time function within the dbms_utility package offers lock resolutions to 100 th
second.
Use an offset when writing back the key. For example, if the key value read is n, then the
application should write back n+1. This is for two reasons. Firstly, if the transaction making the
update only had to specify the same key as was read, then not specifying the key at all would
have the same effect, and so would require the update trigger to include code to check that the
key was being updated.
When a concurrency failure is encountered abort the transaction immediately using PL/SQLs
raise_application_error procedure. Do not attempt to handle the error any other way to do so is
to risk inconsistent data in your database.
Incompatability
If two programs are defined as incompatible with one another, the data these
programs cannot access simultaneously must also be identified.
In other words, to prevent two programs from concurrently accessing or updating the
same data, you have to know where, in terms of data, they are incompatible. A
Conflict Domain identifies the data where two incompatible programs cannot run
simultaneously.
Implementation Strategy
The concurrency should always be enforced at the trigger level.
Using an integer for the concurrency key makes interactive SQL much simpler, and if combined
with the get_time function within the dbms_utility package offers lock resolutions to 100 th
second.
Use an offset when writing back the key. For example, if the key value read is n, then the
application should write back n+1. This is for two reasons. Firstly, if the transaction making the
update only had to specify the same key as was read, then not specifying the key at all would
have the same effect, and so would require the update trigger to include code to check that the
key was being updated.
When a concurrency failure is encountered abort the transaction immediately using PL/SQLs
raise_application_error procedure. Do not attempt to handle the error any other way to do so is
to risk inconsistent data in your database.
Demo
Add Transaction_Control_Number column to the custom
table.
Populate each column with dbms_utility.get_time value.