The REQUEST function is overloaded on the first parameter, which is used to identify the lock by either an INTEGER identifier or by a VARCHAR2 lockhandle.. The headers for this program,
Trang 1PACKAGE BODY printer_access
IS
/* global variables for lock name and handle */
printer_lockname VARCHAR2(128) := 'printer_lock';
printer_lockhandle VARCHAR2(128);
FUNCTION get_printer_lockhandle
RETURN VARCHAR2
IS
BEGIN
IF printer_lockhandle IS NULL
THEN
DBMS_LOCK.ALLOCATE_UNIQUE
(lockname => printer_lockname
,lockhandle => printer_lockhandle);
END IF;
RETURN printer_lockhandle;
END get_printer_lockhandle;
END printer_access;
As illustrated in the example, it is a good idea to call ALLOCATE_UNIQUE only once for any given
lockname per session This is why the function stashes the lockhandle in the global variable,
printer_lockhandle, and calls ALLOCATE_UNIQUE only if this global has not been initialized There are two reasons for using this technique: efficiency and avoidance of extra COMMITs Remember that
ALLOCATE_UNIQUE will always return the same handle for a given lockname and that it always performs
a COMMIT Thus, best practice for using DBMS_LOCK includes calling ALLOCATE_UNIQUE only once per named lock
Locks allocated using ALLOCATE_UNIQUE can be viewed in the Oracle data dictionary via the
DBMS_LOCK_ALLOCATED view
It is good practice to avoid the possibility of lockname conflicts between applications by adopting standard naming conventions for locknames Just as Oracle reserves names that begin with "ORA$", you may want to prefix locknames with your own company and application identifier string
4.1.2.2 The DBMS_LOCK.REQUEST function
The REQUEST function is used to acquire a lock in the mode specified by the lockmode parameter If the lock cannot be acquired in the requested mode within the specified time, the function call completes with a nonzero return value (see the parameter table)
The REQUEST function is overloaded on the first parameter, which is used to identify the lock by either an INTEGER identifier or by a VARCHAR2 lockhandle The release_on_commit parameter indicates whether the lock should persist across RDBMS transactions or be automatically released upon COMMIT or
ROLLBACK The headers for this program, corresponding to each type, are as follows:
FUNCTION DBMS_LOCK.REQUEST
(id IN INTEGER
,lockmode IN INTEGER DEFAULT X_MODE
,timeout IN INTEGER DEFAULT MAXWAIT
,release_on_commit IN BOOLEAN DEFAULT FALSE)
RETURN INTEGER;
FUNCTION DBMS_LOCK.REQUEST
(lockhandle IN VARCHAR2
,lockmode IN INTEGER DEFAULT X_MODE
,timeout IN INTEGER DEFAULT MAXWAIT
,release_on_commit IN BOOLEAN DEFAULT FALSE)
RETURN INTEGER;
Trang 2Parameters for this function are summarized in the following table.
Parameter Description
id Numeric identifier of the lock
lockhandle Handle for lock returned by DBMS_LOCK.ALLOCATE_UNIQUE
lockmode Locking mode requested for lock
timeout Time in seconds to wait for successful conversion
release_on_commit If TRUE, release lock automatically on COMMIT or ROLLBACK
The following table summarizes the return values of the function
Return Value Description
3 Parameter error
4 Do not own lock; cannot convert
5 Illegal lockhandle
The program does not raise any package exceptions
4.1.2.2.1 Restrictions
User−defined lock identifiers must be in the range 0 to 1073741823 Lock identifiers in the range 2000000000
to 2147483647 are reserved for use by Oracle Corporation
4.1.2.2.2 Example
The following procedure calls the REQUEST function to get exclusive access to a lock designated to serialize access to a printer by Oracle sessions It uses the get_printer_lockhandle function (see the example for the ALLOCATE_UNIQUE procedure) to identify the correct value for the lockhandle parameter
PROCEDURE lock_printer
(return_code_OUT OUT INTEGER)
IS
/* initialize variable with desired lockhandle */
temp_lockhandle printer_lockhandle%TYPE := get_printer_lockhandle;
call_status INTEGER;
BEGIN
/*
|| lock in exclusive mode, wait for up to 5 seconds
*/
call_status := DBMS_LOCK.REQUEST
(lockhandle => temp_lockhandle
,lockmode => DBMS_LOCK.x_mode
,timeout => 5
,release_on_commit => TRUE);
return_code_OUT := call_status;
END lock_printer;
It is safest to use the form of REQUEST that identifies the lock by a lockhandle (returned by
Trang 3applications for different purposes, which is possible when locks are identified by integer values chosen by the application
Sessions connected to Oracle using the multithreaded server configuration will not be released from their shared server until all held locks are released Thus, be careful of specifying FALSE for the
release_on_commit parameter in MTS (multithreaded server) environments, as holding locks for long periods could have a negative impact on MTS efficiency
Be sure that distributed transactions specify TRUE for the release_on_commit parameter If a distributed transaction does not release locks after COMMIT, it is possible for a distributed deadlock to occur, which will
be undetectable by either of the databases involved
When two sessions request locks with modes resulting in a deadlock, this is detected by Oracle, and one of the sessions is notified of the deadlock status
4.1.2.3 The DBMS_LOCK.CONVERT function
The CONVERT function is used to convert a previously acquired lock to the mode specified by the lockmode parameter If the mode conversion cannot be granted within the specified time, the function call completes with a nonzero return value (see the following parameter table) CONVERT is overloaded on the first
parameter, which is used to identify the lock by either an INTEGER identifier or a VARCHAR2 lockhandle The headers for this program, corresponding to each type, follow:
FUNCTION DBMS_LOCK.CONVERT
(id IN INTEGER
,lockmode IN INTEGER
,timeout IN NUMBER DEFAULT MAXWAIT)
RETURN INTEGER;
FUNCTION DBMS_LOCK.CONVERT
(lockhandle IN VARCHAR2
,lockmode IN INTEGER
,timeout IN NUMBER DEFAULT MAXWAIT)
RETURN INTEGER;
Parameters for this program are summarized in the following table
Parameter Description
id Numeric identifier of the lock
lockhandle Handle for lock returned by ALLOCATE_UNIQUE
lockmode Locking mode to which to convert the lock
timeout Time in seconds to wait for successful conversion
The return values for this function are summarized in the following table
Return Value Description
3 Parameter error
4 Do not own lock, cannot convert
5 Illegal lockhandle
Trang 4The program does not raise any package exceptions.
4.1.2.3.1 Restrictions
User−defined lock identifiers must be in the range 0 to 1073741823 Lock identifiers in the range 2000000000
to 2147483647 are reserved for use by Oracle Corporation
4.1.2.3.2 Example
The following anonymous PL/SQL block converts a previously acquired lock to null mode, reporting success
or failure to the screen:
DECLARE
call_status INTEGER;
BEGIN
/* convert lock 9999 down to null mode with no wait */
call_status := DBMS_LOCK.CONVERT(9999,DBMS_LOCK.nl_mode,0);
IF call_status = 0
THEN
DBMS_OUTPUT.PUT_LINE('SUCCESS');
ELSE
DBMS_OUTPUT.PUT_LINE('FAIL, RC = '||TO_CHAR(call_status));
END IF;
END;
See the discussion in the "Section 4.1.2.2.2, "Example"" section for the Section 4.1.2.2, "The
DBMS_LOCK.REQUEST function"; all of that discussion also applies to CONVERT
4.1.2.4 The DBMS_LOCK.RELEASE function
The RELEASE function releases a previously acquired lock RELEASE is overloaded on the first parameter, which is used to identify the lock by either an INTEGER identifier or a VARCHAR2 lockhandle The
program headers for each corresponding type follow:
FUNCTION DBMS_LOCK.RELEASE
(id IN INTEGER)
RETURN INTEGER;
FUNCTION DBMS_LOCK.RELEASE
(lockhandle IN VARCHAR2)
RETURN INTEGER;
Parameters are summarized in the following table
Parameter Description
id Numeric identifier of the lock
lockhandle Handle for lock returned by ALLOCATE_UNIQUE
The return values for this function are summarized in the following table
Return Value Description
3 Parameter error
4 Do not own lock; cannot release
5 Illegal lockhandle
Trang 5The program does not raise any package exceptions.
4.1.2.4.1 Restrictions
User−defined lock identifiers must be in the range 0 to 1073741823 Lock identifiers in the range 2000000000
to 2147483647 are reserved for use by Oracle Corporation
4.1.2.4.2 Example
The following procedure calls the RELEASE function to relinquish control of the printer lock (see also the example for the REQUEST function):
PROCEDURE release_printer
(return_code_OUT OUT INTEGER)
IS
/* initialize variable with desired lockhandle */
temp_lockhandle printer_lockhandle%TYPE := get_printer_lockhandle;
call_status INTEGER;
BEGIN
/*
|| release the printer lock
*/
call_status := DBMS_LOCK.RELEASE
(lockhandle => temp_lockhandle);
return_code_OUT := call_status;
END release_printer;
It is good practice to release locks as soon as possible Doing so minimizes the potential for unnecessary wait times or deadlocks in applications where concurrent access to resources is serialized using DBMS_LOCK
4.1.2.5 The DBMS_LOCK.SLEEP procedure
The SLEEP procedure suspends the session for the number of seconds specified in the seconds parameter Sleep periods can be specified with accuracy down to the hundredth of a second (e.g., 1.35 and 1.29 are recognized as distinct sleep times) Here's the header for this program:
PROCEDURE DBMS_LOCK.SLEEP
(seconds IN NUMBER);
4.1.2.5.1 Exceptions
This program does not raise any package exceptions
WARNING: The following nasty Oracle exception was raised on Windows NT when the
SLEEP procedure was called with a NULL value for seconds: ORA−00600: internal error
code, arguments: [15454], [0], [ ], [ ], [ ], [ ], [ ], [ ]
4.1.2.5.2 Restrictions
Do not specify a null value for the seconds parameter; this may result in an ORA−00600 error, as noted previously