CEL:
Chcemy, aby na bazie , dla pewnej grupy funkcjonalności PL/SQL była uruchomiona w danej chwili co najwyżej jedna instancja przetwarzania…
Propozycja rozwiązania:
Wykorzystamy pakiet SYS.DBMS_APPLICATION_INFO ( ma GRANT EXECUTE TO PUBLIC), tabelę TBL_MUTEX , w której będziemy zapisywać parametryzację orazpakiet PCKG_MUTEX
Wymagane uprawnienia:
CREATE TABLE, CREATE PROCEDURE, odczyt z perspektywy systemowej v$session
Elementy DDL:
Szczegóły implementacyjne:
CREATE TABLE TBL_MUTEX
(
PROCESS_NAME VARCHAR2(32 CHAR) NOT NULL,
DESCRIPTION VARCHAR2(50 CHAR) NOT NULL,
F_EXCLUSIVE_RUNNING VARCHAR2(1 CHAR) DEFAULT 'Y' NOT NULL
);
CREATE UNIQUE INDEX IDX_MUTEX ON TBL_MUTEX
(PROCESS_NAME);
ALTER TABLE TBL_MUTEX ADD (
CHECK ("F_EXCLUSIVE_RUNNING" IN('Y','N')),
CONSTRAINT PK_MUTEX
PRIMARY KEY
(PROCESS_NAME));
----------------- PAKIET ---------
CREATE OR REPLACE PACKAGE PCKG_MUTEX IS
PROCEDURE PDB_SetMutex(pc_MutexName VARCHAR2);
PROCEDURE PDB_ClearMutex;
FUNCTION FDB_IsMutexUsed(pc_MutexName VARCHAR2) RETURN NUMBER;
FUNCTION FDB_GetMutexInfo(pc_MutexName VARCHAR2) RETURN VARCHAR2;
PRAGMA RESTRICT_REFERENCES (FDB_IsMutexUsed, WNDS, RNPS);
PRAGMA RESTRICT_REFERENCES (FDB_GetMutexInfo, WNDS, RNPS);
END;
/
CREATE OR REPLACE PACKAGE BODY PCKG_MUTEX IS
CURSOR C_Mutex(pc_MutexName VARCHAR2, pn_CheckSID NUMBER) IS
SELECT
'Na komputerze ' || TRIM(s.terminal) || ' użytkownik '||
TRIM(s.osuser) || ' zalogowany do Oracle jako ' || s.username ||' korzysta z aplikacji ' ||
LTRIM(RTRIM(s.module)) AS Line
FROM v$session s
WHERE
(s.username IS NOT NULL)
AND (NVL (s.osuser, '!!!!!!!!') NOT IN ( 'SYSTEM', 'SYS'))
AND (s.TYPE <> 'BACKGROUND')
AND ((SID <> sys_context('userenv','sessionid') AND pn_CheckSID >0)
OR pn_CheckSID =0 )
AND s.module =
( SELECT process_name FROM TBL_MUTEX WHERE F_EXCLUSIVE_running = 'Y' AND process_name = pc_MutexName
)
;
----------------------------------
FUNCTION FDB_IsMutexUsed(pc_MutexName VARCHAR2) RETURN NUMBER
IS
BEGIN
FOR EL IN C_Mutex(pc_MutexName, 1)
LOOP
RETURN 1;
END LOOP;
RETURN 0;
END;
PROCEDURE PDB_SetMutex(pc_MutexName VARCHAR2)
IS
BEGIN
IF FDB_IsMutexUsed(pc_MutexName) =1 THEN
RAISE_APPLICATION_ERROR(-20100, FDB_GetMutexInfo(pc_MutexName) );
END IF;
DBMS_APPLICATION_INFO.SET_MODULE(pc_MutexName, NULL);
END;
----------------------------------
PROCEDURE PDB_ClearMutex
IS
BEGIN
DBMS_APPLICATION_INFO.SET_MODULE( NULL, NULL);
END;
FUNCTION FDB_GetMutexInfo(pc_MutexName VARCHAR2) RETURN VARCHAR2
IS
BEGIN
FOR EL IN C_Mutex(pc_MutexName,0)
LOOP
RETURN EL.LINE;
END LOOP;
RETURN NULL;
END;
END;
/