Pozdrav,
nakon mnogobrojnih pokusaja sa SELECT FOR UPDATE na kraju sam i odusta od istog i odlucio da na pocetku procedure odmah uradim UPDATE cime bih trebao onemoguciti pristup slogu naredne 3 minute. Nakon UPDATE-a se odmah uradi i COMMIT tako da ostale sesije vide ovu promjenu. Kod izgleda ovako:
Code:
CREATE OR REPLACE procedure PROCEDURA1(
NO_OF_RECS IN INTEGER DEFAULT 100,
BEGIN_ID IN NUMBER DEFAULT 0,
MINUTES_1 IN SMALLINT DEFAULT 2,
MINUTES_2 IN SMALLINT DEFAULT 15,
APPID in number default -1,
RCT1 IN OUT GLOBALPKG.RCT1
)
AS
dateTimeForThisTry DATE;
statusFlagForTry CHAR(1);
minutesToActivate1 INT;
minutesToActivate2 INT;
noOfAttempts1 INT;
noOfAttempts2 INT;
loopControl INT;
myRowCount INT;
Error INT;
ReccCount INT;
strOA VARCHAR2(1024);
strDA VARCHAR2(1024);
timelasttry DATE;
timesystime DATE;
tmpDate date;
BEGIN
ReccCount := 0;
dateTimeForThisTry := (SYSDATE);
statusFlagForTry := 'S';
minutesToActivate1 := MINUTES_1;
minutesToActivate2 := MINUTES_2;
noOfAttempts1 := 3;
noOfAttempts2 := 6;
loopControl := 0;
myRowCount := 0;
Error := 0;
GLOBALPKG.TRANCOUNT := GLOBALPKG.TRANCOUNT + 1;
timesystime := (SYSDATE);
tmpDate := dateTimeForThisTry + TRUNC(minutesToActivate1) /24/60;
begin
update tabela1
set last_try_time = tmpDate, app_id = appid
where ID in(
SELECT
ID
FROM Tabela1
WHERE (MS <> 0 OR OpID <> 1)
AND ID > BEGIN_ID
AND ROUND(( (SYSDATE) - NVL(LAST_TRY_TIME, (SYSDATE)) ) *24*60*60) >= 0--*
AND ROWNUM <= NO_OF_RECS AND REFNUM IN (select REFNUM FROM (SELECT REFNUM, TOTALNUM, COUNT(REFNUM) FROM Tabela1
GROUP BY REFNUM, TOTALNUM
HAVING COUNT(REFNUM) = TOTALNUM)));
COMMIT;
end;
begin
open RCT1 FOR
SELECT
ID,
OpID,
ST,
SMI,
DA,
OA,
NA,
NT,
PID,
DCS,
VP,
DDT,
SCTS,
DT,
RP,
UDL,
UD,
SRR,
MS,
MR,
MMS,
REPLACE,
TRY_COUNT,
STATUS_FLAG,
LAST_TRY_TIME,
PRIORITY,
CDRNUM,
GetSubscriberProfile(trim(OA)) || GetGroupProfile(trim(OA)) as OAProfile,
GetSubscriberProfile(trim(DA)) || GetGroupProfile(trim(DA)) as DAProfile,
GetProfileAutoReply(trim(OA)) as OAAutoReply,
GetProfileAutoReply(trim(DA)) as DAAutoReply,
LAST_TRY_TIME_TEST,
SYSTEM_TIME_TEST
FROM Tabela1
WHERE app_id = appid and last_try_time = tmpDate;
COMMIT;
GLOBALPKG.TRANCOUNT := GLOBALPKG.TRANCOUNT - 1;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
BEGIN
GLOBALPKG.TRANCOUNT := 0;
open RCT1 for select null from dual;
END;
end;
end PROCEDURA1;
Uveo sam novu kolonu app_id u koju se pri updateu upise koja aplikacija je zakljucala slog tako da u nastavku procedure (iz iste procedure) mogu i pokupiti taj slog da bih ga jos i selektovao u REF cursor.
Medjutim ponovo imam isti problem, da dvije aplikacije pokupe iste slogove i duplo ih obrade. Kao da imam problem sa osnovnom konkuretnosti na nivou ORACLA prilikom pristupa slogu. Ne znam da li postoji neko podesenje u bazi koje bi moglo uticati na ovakvo nesto.
Takodjer ne znam postoji li neki drugi mehanizam da se SELECTovani slogovi "zakljucaju" za SELECT od strane druge aplikacije.
Takodjer pokusao sam i sa EXPLICIT lockom na tabeli, i ponovo sam imao isti problem. kao i sa set transaction
isolation level read committed; i nije mi uspjelo.
Ne znam da li postoji jos neki nacin da se "zakljuca" kriticna sekcija u PL/SQL proceduri tj. da proceduru moze pozivati samo jedna aplikacija u jednom trenutku.
Hvala.