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

Pokazywanie postów oznaczonych etykietą mutex. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą mutex. Pokaż wszystkie posty

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