dbms lock emea the traffic lights sessions
TRANSCRIPT
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
1/13
Oracle Session Traffic Lights
Silvia MarroneOracle University Principal Trainer
You have written the code for a complex application, which requires
synchronization between two or more sessions. Your system must also regulate
the start of different applications based on the completion of certain events. For
these requirements the ideal solution is the Oracle supplied package
DBMS_LOCK.
In this edition of OU Experts Corner we illustrate DBMS_LOCKanddemonstrate its usage with an interesting example of synchronising sessions with
an event.
Overview
The DBMS_LOCKpackage provides an interface to Oracle Lock Managementservices, allowing programmers to manage what Oracle refers to as user locks.
Programmers and DBAs may request locks with unique names recognizable in
other procedures in the same or other instances, choose the lock mode, change
the lock mode and release the lock just by using a few simple procedures and
functions. A user lock has all features of a database lock.
User locks can help to:
Synchronize applications and enforce sequential processing
Provide exclusive access to a device, such as a terminal
Provide application-level enforcement of read locks
Detect when a lock is released and cleanup after the application
Note:
Execution privilege on this package is granted by default to the
execute_catalog_role. Consider granting the EXECUTE privilege only to
specific users or roles because there might be operating system-specific limits onthe maximum number of total locks available.
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
2/13
Functions and procedures included in the DBMS_LOCK package:
SQL> desc dbms_lockPROCEDURE ALLOCATE_UNIQUE Argument Name Type In/Out Default?---------------------------- ----------------------- ------ --------LOCKNAME VARCHAR2 INLOCKHANDLE VARCHAR2 OUTEXPIRATION_SECS NUMBER(38) IN DEFAULT
FUNCTION CONVERT RETURNS NUMBER(38) Argument Name Type In/Out Default?---------------------------- ----------------------- ------ --------ID NUMBER(38) INLOCKMODE NUMBER(38) INTIMEOUT NUMBER IN DEFAULT
FUNCTION CONVERT RETURNS NUMBER(38) Argument Name Type In/Out Default?---------------------------- ----------------------- ------ --------LOCKHANDLE VARCHAR2 INLOCKMODE NUMBER(38) INTIMEOUT NUMBER IN DEFAULT
FUNCTION RELEASE RETURNS NUMBER(38) Argument Name Type In/Out Default?---------------------------- ----------------------- ------ --------ID NUMBER(38) IN
FUNCTION RELEASE RETURNS NUMBER(38) Argument Name Type In/Out Default?---------------------------- ----------------------- ------ --------LOCKHANDLE VARCHAR2 IN
FUNCTION REQUEST RETURNS NUMBER(38) Argument Name Type In/Out Default?---------------------------- ----------------------- ------ --------ID NUMBER(38) INLOCKMODE NUMBER(38) IN DEFAULTTIMEOUT NUMBER(38) IN DEFAULTRELEASE_ON_COMMIT BOOLEAN IN DEFAULT
FUNCTION REQUEST RETURNS NUMBER(38) Argument Name Type In/Out Default?---------------------------- ----------------------- ------ --------LOCKHANDLE VARCHAR2 INLOCKMODE NUMBER(38) IN DEFAULTTIMEOUT NUMBER(38) IN DEFAULTRELEASE_ON_COMMIT BOOLEAN IN DEFAULT
PROCEDURE SLEEP Argument Name Type In/Out Default?---------------------------- ----------------------- ------ --------SECONDS NUMBER IN
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
3/13
PROCEDURE ALLOCATE_UNIQUE: allocate a unique lock given a name. The
procedure has three parameters:
- lockname: input parameter that is the name of the lock for which
to generate unique lockid . The name can be up to 128 bytes, and itis case-sensitive. If this name already has been assigned a lockid,
then return a handle to that lockid. Otherwise generate a new
lockid and return a handle to it.
- lockhandle: output parameter that is not the actual lockid but ahandle (up to 128 bytes). This handle can be used in subsequent
calls to request, convert and release locks. A handle is used to
reduce the chance that a programming error can accidentally
create an incorrect but valid lockid. This will provide better
isolation between different applications that are using this
package.
- expiration_secs: output parameter containing the number ofseconds after an 'allocate_unique' is most recently performed on
this lock name, that this lock is subject to cleanup. The default
value is 864000 sec (10 days).
The information about name, lock id and expiration date can be found in the
dbms_lock_allocatedtable.
SQL> desc dbms_lock_allocated Name Null? Type--------------------------------------- -------- --------------
NAME NOT NULL VARCHAR2(128)LOCKID NUMBER(38)EXPIRATION DATE
All sessions invoking the allocate_unique procedure using the same name will
refer to the same lock, but the lockhandle returned by the procedure could bedifferent. The lockid's generated by allocate_unique are between 1073741824and 1999999999 inclusive.
Note: This procedure will always do a commit.
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
4/13
FUNCTION REQUEST: request a lock in a given mode. There are two request
functions differening only in the first parameter which is either of the
following:
- id: input parameter that is the lock id. The value may range from0 to 1073741823. Numbers between 2000000000 to 2147483647 are
reserved for products supplied by Oracle Corporation and should
not be used.
- lockhandle: input parameter, is the handle originally returnedby the allocate_unique procedure.
For either function the following parameters exist:
-
lockmode: input parameter. There are five different lockmodes
the default being exclusive mode.
nl NuLl
ss Sub Shared
sx Sub eXclusive
s Shared
ssx Shared Sub eXclusive
x eXclusive
This is the lock compatibility table:
held get-> NL SS SX S SSX X NL SUCC SUCC SUCC SUCC SUCC SUCCSS SUCC SUCC SUCC SUCC SUCC failSX SUCC SUCC SUCC fail fail failS SUCC SUCC fail SUCC fail failSSX SUCC SUCC fail fail fail failX SUCC fail fail fail fail fail
- timeout: input parameter in seconds. If the lock cannot be
acquired within this time period then the function returns a valueof 1 (timeout see below). The default value is 32767 sec.
- release_on_commit: input parameter. The default value isFALSE meaning that the lock must be released explicitely with the
release function or at the end of the session. IfTRUE the lock will be
released on commit or rollback.
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
5/13
The function returns a number. The possible values and meanings are as
follows:
0 success
1 timeout2 deadlock
3 parameter error
4 already own lock specified by 'id' or 'lockhandle'
5 illegal lockhandle
FUNCTION CONVERT: convert lock from one mode to another. This function is
overloaded on the first parameter as before. The parameters are:
- id: input parameter that is the lock id. The values admitted arefrom 0 to 1073741823 or
- lockhandle: input parameter, is the handle returned by theallocate_unique procedure.
For either function:
- lockmode: input parameter. See above the lockmode parameterof the request function
- timeout: input parameter in seconds. If the lock cannot beconverted within this time period, the funcion returns the value 1
(timeout). The default value is 32767 sec.
The function returns a number. The possible values are the same of the
request function (see above)
FUNCTION RELEASE: release the lock previously acquired by the request
function. This function is also overloaded. The parameters are:
- id: input parameter that is the lock id. The values admitted arefrom 0 to 1073741823 or
- lockhandle: input parameter, is the handle returned by theallocate_unique procedure.
The function returns a number. The possible values are:
0 success
3 parameter error
4 don't own lock specified by 'id' or 'lockhandle'
5 illegal lockhandle
PROCEDURE SLEEP: Suspend the session for the specified period of time.
The only input parameter is seconds. The maximum resolution is inhundreths of a second
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
6/13
The package specification also contains six constants that correspond to the six
lock modes:
nl_mode constant integer := 1; => NuLlss_mode constant integer := 2; => Sub Sharedsx_mode constant integer := 3; => Sub eXclusives_mode constant integer := 4; => Sharedssx_mode constant integer := 5; => Shared Sub eXclusivex_mode constant integer := 6; => eXclusive
Using the DBMS_LOCK package to synchronize sessions.
Two or more sessions are required to perform some task at the same time. In our
example we will use three sessions and the task will be to insert the time into the
following table.
CREATE TABLE lock_test (session_id number,action VARCHAR2(10),when date);
In the first session we now execute the following anonimous PL/SQL block to
acquire an exclusive lock.
Set serveroutput ondeclarev_lockhandle varchar2(200); v_result number;
begin
dbms_lock.allocate_unique('sync_lock', v_lockhandle);
v_result := dbms_lock.request(v_lockhandle, dbms_lock.x_mode);
dbms_output.put_line(
casewhen v_result=0 then 'Success'when v_result=1 then 'Timeout'when v_result=2 then 'Deadlock'when v_result=3 then 'Parameter Error'when v_result=4 then 'Already owned'when v_result=5 then 'Illegal Lock Handle'
end);end;/
The result should be Success.
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
7/13
Lets examine the dbms_lock_allocatedtable:
Now lets see what is in the dba_lock view or the dba_locks synonym.
SQL> desc dba_locks Name Null? Type-------------------------------------------- -------- --------------
--SESSION_ID NUMBERLOCK_TYPE VARCHAR2(26) MODE_HELD MODE_REQUESTED LOCK_ID1 VARCHAR2(40)LOCK_ID2 VARCHAR2(40)LAST_CONVERT NUMBERBLOCKING_OTHERS VARCHAR2(40)
Note: To create this view and synonym execute the catblock.sql script in
$ORACLE_HOME/rdbms/admindirectory.
SQL> select * from dbms_lock_allocated;
NAME LOCKID EXPIRATION-------------------- ---------- --------------------sync_lock 1073741853 19-OCT-2008 14:15:32
SQL> select * from dba_locks;
SESSION_ID LOCK_TYPE MODE_HELD MODE_REQUE LOCK_ID1 LOCK_ID2 LAST_CONVERT BLOCKING_OTH
---------- ---------------- ---------- ---------- ---------- ---------- ------------ ------------
164 XR Null None 4 0 1456 Not Blocking
164 Control File Row-S (SS) None 0 0 1450 Not Blocking
164 RS Row-S (SS) None 25 1 1447 Not Blocking
166 PW Row-X (SX) None 1 0 1441 Not Blocking
165 Redo Thread Exclusive None 1 0 1447 Not Blocking
121 PL/SQL User Lock Exclusive None 1073741853 0 236 Not Blocking
166 Media Recovery Share None 1 0 1444 Not Blocking
166 Media Recovery Share None 2 0 1444 Not Blocking
166 Media Recovery Share None 3 0 1444 Not Blocking166 Media Recovery Share None 4 0 1444 Not Blocking
166 Media Recovery Share None 5 0 1444 Not Blocking
166 Media Recovery Share None 6 0 1444 Not Blocking
166 Media Recovery Share None 201 0 1444 Not Blocking
163 Temp Segment Row-X (SX) None 3 1 1439 Not Blocking
14 rows selected.
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
8/13
In this example we are interested in the row, with SESSION_ID 121 and LOCK_ID1
1073741853 highlighted in red.
We now start two additional sessions and execute the following PL/SQL in eachsession:
set serveroutput ondeclare v_result number;v_lockhandle varchar2(200);
begin
dbms_lock.allocate_unique('sync_lock', v_lockhandle);
v_result := dbms_lock.request(v_lockhandle, dbms_lock.ss_mode);
dbms_output.put_line(
casewhen v_result=0 then 'Success'when v_result=1 then 'Timeout'when v_result=2 then 'Deadlock'when v_result=3 then 'Parameter Error'when v_result=4 then 'Already owned'when v_result=5 then 'Illegal Lock Handle'
end);
insert into lock_testvalues (SYS_CONTEXT ('USERENV', 'SID'),'started', sysdate);
dbms_lock.sleep(5);
insert into lock_testvalues (SYS_CONTEXT ('USERENV', 'SID'), 'ended' , sysdate);
commit;
end;/
Note: the function SYS_CONTEXT ('USERENV', 'SID') returns the SID ofthe session. In other words, the value of the columnV$SESSION.SID.
The code block requests a shared lock with the same name as was requested by
the first session. This shared lock cannot be acquired if another session holds an
exclusive lock (see above the compatibility chart). This means that the two
sessions are blocked and will now wait until the owning session releases the lock.
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
9/13
Lets reexamine DBA_LOCKS to see the owner and waiters:
We have two additional rows for SESSION_IDs 153 and 133, which areblocked trying to acquire a shared lock as seen in theMODE_REQUESTED column.
Session 121 is now a blocking session!
The DBA_WAITERS view gives us the same information. Session 121 is a holding
session, with an exclusive lock. The other two sessions, 153 and 133, are waiting
to acquire a shared lock.
SQL> select * from dba_locks;
SESSION_ID LOCK_TYPE MODE_HELD MODE_REQUE LOCK_ID1 LOCK_ID2 LAST_CONVERT BLOCKING_OTH
---------- ---------------- ---------- ---------- ---------- ---------- ------------ ------------
164 XR Null None 4 0 1936 Not Blocking
164 Control File Row-S (SS) None 0 0 1930 Not Blocking
164 RS Row-S (SS) None 25 1 1927 Not Blocking
166 PW Row-X (SX) None 1 0 1921 Not Blocking
165 Redo Thread Exclusive None 1 0 1927 Not Blocking
121 PL/SQL User Lock Exclusive None 1073741853 0 716 Blocking
153 PL/SQL User Lock None Row-S (SS) 1073741853 0 24 Not Blocking
133 PL/SQL User Lock None Row-S (SS) 1073741853 0 18 Not Blocking
166 Media Recovery Share None 1 0 1924 Not Blocking
166 Media Recovery Share None 2 0 1924 Not Blocking
166 Media Recovery Share None 3 0 1924 Not Blocking
166 Media Recovery Share None 4 0 1924 Not Blocking
166 Media Recovery Share None 5 0 1924 Not Blocking
166 Media Recovery Share None 6 0 1924 Not Blocking
166 Media Recovery Share None 201 0 1924 Not Blocking
163 Temp Segment Row-X (SX) None 3 1 1919 Not Blocking
16 rows selected.
SQL> select * from dba_waiters;
WAITING_SESSION HOLDING_SESSION LOCK_TYPE MODE_HELD MODE_REQUE LOCK_ID1 LOCK_ID2
--------------- --------------- ---------------- ---------- ---------- ---------- ----------
153 121 PL/SQL User Lock Exclusive Row-S (SS) 1073741853 0
133 121 PL/SQL User Lock Exclusive Row-S (SS) 1073741853 0
153 133 PL/SQL User Lock None Row-S (SS) 1073741853 0
133 133 PL/SQL User Lock None Row-S (SS) 1073741853 0
153 153 PL/SQL User Lock None Row-S (SS) 1073741853 0
133 153 PL/SQL User Lock None Row-S (SS) 1073741853 0
6 rows selected.
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
10/13
Another way to see the same information is by executing the script
utllockt.sql located in $ORACLE_HOME/rdbms/admin directory. Theoutput looks as follows:
One remaining view for accessing lock information isV$LOCK.
SQL> desc v$lock Name Null? Type----------------- ----------------------- ---------- --------------- ADDR RAWKADDR RAW(4)SID NUMBERTYPE VARCHAR2(2)ID1 NUMBERID2 NUMBERLMODE NUMBERREQUEST NUMBERCTIME NUMBERBLOCK NUMBER
WAITING_SESSION LOCK_TYPE MODE_REQUE MODE_HELD LOCK_ID1 LOCK_ID2
----------------- ----------------- ---------- ---------- ----------------- -----------------
121 None
153 PL/SQL User Lock Row-S (SS) Exclusive 1073741853 0
133 PL/SQL User Lock Row-S (SS) Exclusive 1073741853 0
SQL> select * from v$lock;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
33834228 3383423C 165 XR 4 0 1 0 2760 0
33834284 33834298 165 CF 0 0 2 0 2760 0
338342E0 338342F4 167 PW 1 0 3 0 2746 0
3383433C 33834350 165 RS 25 1 2 0 2750 0
338343F4 33834408 166 RT 1 0 6 0 2750 0
33834450 33834464 121 UL 1073741853 0 6 0 264 1
338344AC 338344C0 153 UL 1073741853 0 0 2 253 0
33834508 3383451C 133 UL 1073741853 0 0 2 250 033834564 33834578 167 MR 1 0 4 0 2750 0
338345C0 338345D4 167 MR 2 0 4 0 2750 0
3383461C 33834630 167 MR 3 0 4 0 2750 0
33834678 3383468C 167 MR 4 0 4 0 2750 0
338346D4 338346E8 167 MR 5 0 4 0 2750 0
33834730 33834744 167 MR 6 0 4 0 2750 0
3383478C 338347A0 167 MR 201 0 4 0 2750 0
33834844 33834858 164 TS 3 1 3 0 2741 0
16 rows selected.
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
11/13
The column TYPE is the type of user or system lock. The value UL means UserLock.
Lock information is also available in the Blocking Session page of Enterprise
Manager.
Note: User locks never conflict with Oracle locks.
Now lets return to the first session and release the exclusive lock using the
following PL/SQL block.
declarev_lockhandle varchar2(200); v_result number;
begin
dbms_lock.allocate_unique('sync_lock', v_lockhandle);
v_result := dbms_lock.release(v_lockhandle);
dbms_output.put_line(case
when v_result=0 then 'Success'when v_result=1 then 'Timeout'when v_result=2 then 'Deadlock'when v_result=3 then 'Parameter Error'when v_result=4 then 'Already owned'when v_result=5 then 'Illegal Lock Handle'
end);
end;
/
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
12/13
Sessions 153 and 133 are now free and there are no more blocking sessions as can
be seen in the output below. The two sessions do not block each other because
they hold a lock which may be shared according to the lock compatibility chart
shown earlier.
The two sessions require five seconds to finish because of thedbms_lock.sleep(5)procedure call used between the two insert statements.
Note: The DBMS_LOCK.SLEEP procedure sleeps for the wrong period of time ifthe time interval is more then 1 hour. This is due to bug number 1842189.
A workaround is to use the DBMS_BACKUP_RESTORE.SLEEP procedure whichsleeps properly even if the time interval is more than 1 hour.
Now lets see what the sessions have written into the lock_test table:
SQL> alter session set NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';SQL> SELECT * FROM lock_test;
SESSION_ID ACTION WHEN---------- ---------- --------------------
153 started 09-OCT-2008 14:39:05153 ended 09-OCT-2008 14:39:10133 started 09-OCT-2008 14:39:05133 ended 09-OCT-2008 14:39:10
Notice that both sessions start at the same time and therefore were exactly
synchronised with the release of the lock by the lock holder!
SQL> select * from dba_locks;
SESSION_ID LOCK_TYPE MODE_HELD MODE_REQUE LOCK_ID1 LOCK_ID2 LAST_CONVERT BLOCKING_OTH
---------- ---------------- ---------- ---------- ---------- ---------- ------------ ------------
164 XR Null None 4 0 3127 Not Blocking
164 Control File Row-S (SS) None 0 0 3121 Not Blocking
164 RS Row-S (SS) None 25 1 3118 Not Blocking
166 PW Row-X (SX) None 1 0 3112 Not Blocking
165 Redo Thread Exclusive None 1 0 3118 Not Blocking
153 PL/SQL User Lock Row-S (SS) None 1073741853 0 41 Not Blocking
133 PL/SQL User Lock Row-S (SS) None 1073741853 0 41 Not Blocking
166 Media Recovery Share None 1 0 3115 Not Blocking
166 Media Recovery Share None 2 0 3115 Not Blocking
166 Media Recovery Share None 3 0 3115 Not Blocking
166 Media Recovery Share None 4 0 3115 Not Blocking
166 Media Recovery Share None 5 0 3115 Not Blocking
166 Media Recovery Share None 6 0 3115 Not Blocking
166 Media Recovery Share None 201 0 3115 Not Blocking
163 Temp Segment Row-X (SX) None 3 1 3110 Not Blocking
15 rows selected.
-
8/6/2019 DBMS LOCK Emea the Traffic Lights Sessions
13/13
An example of PL/SQL block to convert a lock mode is the following:
declare v_result number;
begin
v_result := dbms_lock.convert('1073741853', dbms_lock.sx_mode);dbms_output.put_line(
casewhen v_result=0 then 'Success'when v_result=1 then 'Timeout'when v_result=2 then 'Deadlock'when v_result=3 then 'Parameter Error'when v_result=4 then 'Already owned'when v_result=5 then 'Illegal Lock Handle'
end);end;/
You may choose any of the six lock modes. This was not used in our example but
may be useful to change the mode of a lock owner so that for example other
sessions may access the lock in certain modes but not others.
Conclusions
In this article we have covered these subjects:
An overview of the usage of the Oracle Supplied Package DBMS_LOCK.
The explanation of all functions and procedures included in DBMS_LOCKpackage.
Using DBMS_LOCKto synchronyze two or more sessions with an event oreach other.
Methods used to retrieve lock information using command line views and
Enterprise manager.