dbms lock emea the traffic lights sessions

Upload: piciul7001

Post on 07-Apr-2018

216 views

Category:

Documents


0 download

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.