Oracle Table Lock Modes
Oracle Table Lock Modes
TIPS&TECHNIQUES
&RANCK 0ACHOT 4RIVADIS 3!
Lock Types
A lock is a mechanism used to
serialize access to a resource. As concurrent sessions will wait for the resource, as in a queue, they are also
called enqueues, and this is the term
used in wait events to measure the time
waited. Oracle uses locks to:
protect data as tables, rows, index
entries, (DML Locks)
protect metadata in the dictionary
or in the shared pool (Data Dictionary Lock)
or to protect internal objects in
memory (Latches, Mutextes and
other internal locks).
Here we will be talking about data
only. Data locks are also called DML
locks because they are used for DML
(Data Manipulation Language), but
they are also used by DDL (Data Definition Language) when it accesses data.
There are three types of DML locks:
Row level locks are called transaction locks (TX) because, even if
they are triggered by a concurrent
Lock Modes
Basically, a resource can be locked
in two modes: Exclusive (to prevent
any concurrent access) or Share (to
prevent only exclusive access). But
Oracle has defined 6 modes (including
the no lock mode) and each one has
Mode 1:
Null
NL
Mode 2: SS
RS
Row S
Row Share
SubShare
Mode 3: SX
RX
Row X
Row Exclusive
SubExclusive
Mode 4: S
Mode 6: X
Share
S
Share Row Exclusive Share SubExclusive
Exclusive
C
X
TIPS&TECHNIQUES
And when we look at the wait events,
from V$SESSION, or from the Blocking
Sessions screen of Entreprise Manager, we dont have those names but a
number:
P1TEXT
TM mode 1:
P1
name/mode 1414332417
P1RAW
544D0001
TM mode 4:
TM mode 5:
TM mode 6:
TX mode 4:
TX mode 6:
Share / Exclusive
An exclusive lock (X) disallows to
share a resource: it prevents another
session to acquire a share lock (S) or
an exclusive lock (X) on the same resource.
A share lock (S) allows sharing a
resource: multiple sessions can acquire a share lock (S) on the same resource. But it prevents another session
to acquire an exclusive lock (X) on the
same resource. When reading data, we
usually want to prevent concurrent
writes, so we need a share access on it.
Here we have the basic elements to
understand and remember the compatibility matrix: For X and S locks, the
matrix is: S/S are compatible but S/X,
and X/X are not compatible.
The general idea behind X (exclusive) and S (share) is that
When we need to write data, we
acquire an exclusive lock.
When we need to read the data
and make sure that no one is writing concurrently, then we acquire a
share lock. If someone is already
updating the data (holding an X
Sub / Row
We have seen that there are sometimes two names and two abbreviations for the same mode: Sub (S) and
Row (R).
Lets focus on table locks. The resource locked by Share (S) and Exclusive (X) is a table. And a table is made
of rows. Oracle has lock modes that
can be acquired on a resource, but that
concern only a subpart of the locked
resource. If the resource is a table, then
the subparts are rows.
For example, if we update one or
more records in a table (insert, update,
or delete), we are writing so we need an
exclusive lock. But we are not writing
on the whole table. We do not need to
lock the whole table in exclusive mode.
So we will acquire a lock that concerns
only some rows. This is the Row X lock
(Row Exclusive). Similarly, if we want to
acquire a lock for blocking reads (reading data and prevent concurrent modification on what we read), as the select
for update did before version 9i, then
rather than acquiring a Share lock on
whole table we can acquire a Row S
(Row Share) lock.
We are at table level but we acquire
Row S and Row X locks for row modification.
Here is the reason for the dual naming Sub/Row: in the case of a table
lock, the subparts are Rows, so we can
talk about Row S (RS) and Row X (RX).
But in the general case, for a lock acquired for a Subpart of a resource, the
name is Sub S (Sub Share) and Sub X
(Sub Exclusive).
And even for a table lock, if the table is partitioned, then an exclusive
19
Table level /
Row level
Here we have been talking about
locks acquired at table level (TM locks)
even if they concern subparts.
Besides that, the DML operations
(INSERT, UPDATE, DELETE or SELECT
FOR UPDATE) have to acquire locks at
row level. Two sessions can concurrently modify rows in the same table if
they do not touch the same row. And
we have seen that this requires a TMRX (Row-X) lock on the table. However,
in addition to that table level lock,
each session will also acquire a lock on
the row itself: within the block, the row
will have a lock flag, which is a pointer
to the ITL entry, which identifies the
transaction that has updated the row.
It is a row level lock but the resource that is locked is actually the
transaction, which is the reason why it
is a called a TX lock. A transaction sees
that a row is locked by another transaction, and then it will request a lock on
the transaction that locked the rows waiting for end of that transaction.
That TX lock is always exclusive:
Oracle did not implement share lock at
the record level (Other RDBMS needs it
for transaction isolation, but Oracle
uses multi versioning for that).
So, we have table locks that concern the whole table (TM locks in mode
S and X) and we have row level locks
(TX locks).
Then what is the reason for table
level row locks (TM locks in mode
Row-S and Row-X) ?
A table can have millions of rows.
When we need a share lock on the table (TM-Share), it would not be efficient
to scan all the table rows in order to see
if there are some rows that are locked.
In the other way, acquiring an exclusive
lock at table level when we need to update only few rows would be disastrous
for concurrency and scalability.
20
TIPS&TECHNIQUES
Read / Write
We have seen that the general idea
is that an exclusive lock (X) is acquired
when you are writing and a share lock
(S) is acquired when you are reading
and want that read to prevent concurrent writes.
In the same way, a Sub eXclusive
lock (RX or SX) is acquired when you
have the intention to write a subpart,
and a Sub Share lock (RS or SS) is acquired when you have the intention to
do a blocking reads on a subpart.
But in Oracle, we have to go further:
Oracle performs non blocking reads by
default, meaning that you can read
consistent data without having to block
concurrent writes (See Tom Kyte link
below). Those reads are known as
query mode or consistent read.
They do not lock the data because they
do not have to read the current version
of the blocks. If there is concurrent
writes on the block, they build a previous version of it by applying undo
information.
When you want to do a blocking
read, you use a select for update
which locks the row without updating it
(event if it is often done with the goal to
update it as the name suggests). Until
9i, the select for update acquired a
share lock (Row-S), which is still in the
idea of reading. But from 9i, an exclusive lock is acquired: the select for update has the same locking behavior
than an update. Besides that, at row
level, the select for update lock
has always been an exclusive TX lock.
Table operations
SELECT, without a for update, is
a non blocking read, so it does not acquire any lock in Oracle. You can even
drop a table while another session is
reading it.
INSERT, UPDATE, DELETE, have
the intention to write on some rows, so
they acquires a Row X mode table lock
(in addition to the row level TX locks).
SELECT FOR UPDATE is doing
blocking reads on some rows, so it acquired a Row S before 9i. But now it
has the same behavior as an update
and acquires a Row X.
DML with referential integrity
need additional locks. For example,
when you insert into a child table, then
the existence of the parent must be
checked with a blocking read. If it were
not the case, the parent could be deleted before we commit our transaction
and integrity would be violated. This is
similar to SELECT FOR UPDATE and
acquires a Row X on the parent (it was
Row S before 9i). In the other way, deleting a parent row or changing its referenced values (usually the primary
key) need to prevent a concurrent insert on the child that could reference
the deleted parent. This is a Row X
(Row S before 11g) if child has an index
that can have a row level lock on it for
the parent value. If there is no index
that starts with the foreign key, then a
Share lock is acquired during the delete
statement, blocking any DML.
If the referential integrity has an ON
DELETE CASCADE, then the Share
lock requested by the unindexed foreign keys become a Share Row Exclusive one as it adds the Row-X from the
delete.
A direct path INSERT has to prevent any concurrent modification, thus
it acquires an X lock on the table. If it is
inserted into a specific partition (naming the partition with the table name),
then the table has a Sub-X lock for the
intention to write on a subpart, and the
partition has an X lock.
All those locks are acquired until the
end of the transaction (commit or rollback) at the exception of the TM-Share
of non-indexed foreign keys that is released faster.
DDL can acquire locks, for the
whole operation or for only a short period (and then it can be considered as
an online operation).
TIPS&TECHNIQUES
When you need to achieve repeatable reads (to avoid phantom reads
concurrent inserts that would change
your result set) then you cannot rely on
row level locks (TX) for an obvious reason: you cannot lock a row that do not
exists yet (there is no range lock in
Oracle). Then you need to lock the
whole table and this is done with a
Share lock. For example, if you create
an index, or rebuild it without the online
option, the DDL acquires a TM-Share
lock on the table.
And when a DDL need exclusive
write access, such an ALTER TABLE
MOVE, a TM-X mode lock is acquired.
Those are just examples. There are
many situations that we cannot explain
here and that change with versions.
But thinking about which the set of
data that is written, and which one
need to be read with blocking reads,
will help you to understand what happens.
In addition to that, you can acquire
table locks with the LOCK TABLE statement and following modes: ROW
SHARE, ROW EXCLUSIVE, SHARE,
SHARE ROW EXCLUSIVE, EXCLUSIVE.
You think there are already too
many synonyms for Row-S, Sub-S
etc.? Here is another one: you can acquire it with LOCK TABLE IN SHARE
UPDATE MODE
21
Compatibility Matrix
The whole reason for all those lock
modes is to allow or disallow (or serialize) concurrent access on a resource.
So we need to know which one are
compatible or not.
The lock compatibility matrix shows
that.
Compatible locks?
Row-S (RS)
Row-S
(RS)
Row-X
(RX)
Share
(S)
S/Row-X Exclusive
(SRX)
(X)
Row-X (RX)
Share (S)
S/Row-X (SRX)
Exclusive (X)
Did you ever read and try to remember that compatibility matrix? Now that
we understand the meaning of each
mode, it can be easier. Lets build it
from the definitions we have seen
above.
We already have seen the compatibility about X and S: by definition,
the matrix shows that S/S are compatible but S/X and X/X are not.
About subparts, this is different.
Modifying a few rows in a table does
not prevent another session to modify
some (other) rows in the same table.
The row by row conflict is managed by
the row level locks (TX) but here we are
talking about table locks (TM). Therefore the matrix shows that RS/RS, RX/
RX, RS/RX are compatible.
But among resources and sub
resources, there may be conflict, and
this is the reason for Sub locks: If the
22
TIPS&TECHNIQUES
Dictionary Views
This is enough theory. We will now check how to see
locks in our Oracle instance.
Lets do a DML operation and see which information can
be gathered from dictionary views.
SESSION1> select sid from v$mystat where rownum=1;
SID
---------13
SESSION1> update test set dummy='Y';
1 row updated.
TIPS&TECHNIQUES
23
Our first session (SID 13) still have the same locks, but we
know that the DML lock is blocking another session.
SESSION_I
--------13
13
LOCK_TYPE
MODE_HELD
--------- ---------DML
Row-X (SX)
Transaction Exclusive
MODE_REQUESTED LOCK_ID1
-------------- -------None
723764
None
524303
LOCK_ID2
-------0
43037
LAST_CONVERT BLOCKING_OTHERS
------------ ------------10 Blocking
10 Not Blocking
MODE_REQUESTED MODE_HELD
-------------- -------------
LOCK_ID1
----------------
LOCK_ID2
---------------
Share
723764
Row-X (SX)
24
TIPS&TECHNIQUES
Here we see that second session session (SID 47) is currently waiting on a TM lock (enqueue). It has been waiting for
802 seconds (I ran that query a few minutes later). P2 is the
object_id (object #) and P1 is the lock type and mode
(name|mode) encoded in hexadecimal:544Dis the ascii code
for TM and4is the lock mode (Share). So we can have all
information from waits events: session 47 is waiting for 802
seconds to acquire a TM lock in mode S on table TEST.
This is where the Table 2 - enqueue wait event parameters
is useful.
V$SESSION_EVENT shows wait event statistics cumulated
for the sessions.
SQL> select * from v$session_wait where event like enq%;
SID
EVENT
TOTAL_WAITS TOTAL_TIMEOUTS
---------- -------------------- ----------- -------------47 enq: TM - contention
296
281
TIME_WAITED
----------86490
AVERAGE_WAIT MAX_WAIT
------------ --------292.2
295
We see our TM lock on which the session has been waiting 86490 centiseconds (865 seconds, I ran that query one
minute after the previous one). I know that there were only
one request for that lock, but 296 enqueue wait have been
accounted for it. This is because waiting for a lock is not done
with only one wait. The wait times out after 3 seconds (thats
why you see the average wait time about 300 centiseconds,
and that you have a number of timeouts that reaches the
number if waits). This is the way it works: after 3 seconds
waiting, the process takes control again, checks if it is not in
a deadlock situation, and then waits another 3 seconds.
So Im in session 18 and I ran an update that has not updated any rows.
SESSION1> select * from dba_locks where session_id=18;
SESSION_ID LOCK_TYPE
MODE_HELD
MODE_REQUESTED LOCK_ID1 LOCK_ID2 LAST_CONVERT BLOCKING_OTHERS
---------- ------------ ------------ -------------- -------- -------- ------------ --------------18 DML Row-X (SX)
None
723764
0
1 Not Blocking
TIPS&TECHNIQUES
25
Deadlock graph
When locks are in a deadlock situation, Oracle will kill one
session and dump the information in the session tracefile. If
you have frequent deadlocks for table locks, that must be
fixed in the application design. But you need to know what
happened, and you have to read the dump file.
Here is an example where each session was waiting on
the other:
Deadlock graph:
Resource Name
TM-000215da-00000000
TM-000215d9-00000000
26
TIPS&TECHNIQUES
Event 10704
trace enqueues
If you want to go further, and have a trace for each lock
that is acquired and released by a session, then you can set
the event 10704 at least in level 2. In the trace file you will be
interested mainly by lines such as:
and
ksqrcl: TM,16ae5,0
The first one is for the Get Lock: here a table lock (TM)
lock is acquired for object id 16ae5 in Row-X (3)
The second one shows when the lock was released.
You can also see lock conversion from one mode to another with:
ksqcnv TM-00016ae5-00000000 mode=5 timeout=21474836
References
Oracle Documentation
http://download.oracle.com/docs/cd/E11882_01/server.112/e10713/consist.
Thomas Kyte
Consistent Reads
htm#CNCPT1340
http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_
Kyle Hailey
ID:27330770500351
http://www.perfvision.com/papers/09_enqueues.ppt
Oracle Comments
ORACLE_HOME/rdbms/admin/dbmslock.sql
SMS
>>>
TIPS&TECHNIQUES
27
Blocking locks in
Enterprise Manager
Locked sessions are easily shown in
Entreprise Manager from their enqueue
wait event.
They are shown in red in the Top Activity chart (Figure 1 OEM Performance / Top Activity)
And the equivalent to utllockt.sql is
in the Blocking Sessions screen (Figure
2 OEM 12c Performance - Blocking
Sessions).
However, this is where it is good to
know the decimal values for P1 that we
have in Table 2 - enqueue wait event parameters, so that we can easily recognize TM-Share when we see the value
1414332420 and check for un-indexed
foreign keys.
Figure 1
OEM Performance / Top Activity
Figure 2
OEM 12c Performance - Blocking Sessions
Contact
Trivadis SA
Franck Pachot
E-Mail:
[email protected]