Blog programisty w Oracle PL/SQL

Jest to blog eksperymentatora programisty w PL/SQL dla Oracle. Wszystkie kody tutaj zamieszczone mogą być dowolnie wykorzystywane i zmieniane. A jeśli Ktoś z Gości znajdzie błąd, będę niezwykle wdzięczny...
Zapisz

Szukaj na tym blogu

czwartek, 17 lutego 2011

Prosta namiastka mutexu na bazie dla funkcjonalności PL/SQL

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;
/