Newsgroup: it.comp.software.database
Titolo: [ORACLE] stored procedure "sincronizzate"

Ciao a tutti,
ho la necessita' di "sincronizzare" delle stored procedure, sincronizzare
sul modello java, cioe' permettere l'esecuzione di una stored procedure solo
da un utente alla volta, non in modo contemporaneo. Come posso fare?
Il mio problema risiede nel fatto che all'interno di una complessa stored
procedure, vengono fatti dei controlli che portano poi a degli update.
L'esecuzione contemporanea di questa sp, puo' portare a casi di concorrenza
nei quali l'update finale e' effettuato anche quando invece non doveva
esserlo perche' l'update di un altro processo arriva "in ritardo" rispetto
ai controlli iniziali.
Pietro
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 
Ciao Pietro,
se il problema e' solo quello di inibire un update puoi porre un lock 
sulla tabella o la riga da modificare all'inizio della store procedure e 
rilasciare il lock alla fine.
Devo dire che potresti magari lavorare con qualcosa di piu' raffinato 
come l'apertura esplicita di una transazione ma in quel caso ti 
consiglio di leggerti il manuale oracle per la parte relativa agli 
"isolation levels".
-- 
Fabrizio Magni
fabrizi...@mycontinent.com
replace mycontinent with europe

 ha
scritto:

Ciao Fabrizio. Innanzitutto grazie per la risposta. Il problema non e' solo
nell'"update". Mi sono espresso male perche' oltre che update ci sono insert
ecc. cioe' operazioni di aggiornamento. Il problema e' che le linee dove
risiedono queste operazioni, dopo i controlli che stanno a monte, non
dovrebbero neanche essere raggiunte da un processo concorrente perche' i
controlli precedenti dovrebbero fallire e farlo uscire dalla sp. Quindi il
problema non e' regolare l'accesso alla tabella (o alle tabelle) in fase di
insert/update ma essere sicuri che i controlli siano effettuati solo quando
un processo ha terminato la fare di update/insert sulla/e tabella/e.
A meno che non possa inserire un lock anche per la sola lettura sulle
tabelle (meglio se su una sola riga delle tabelle) per tutte quelle tabelle
che vengono consultate per i controlli iniziali...


 
Ciao Pietro,
forse, prima di andare avanti sull'implementazione, ti conviene fare un 
paio di passi indietro sul design (non prendere la cosa come un'offesa).
Un RDBMS e' di per se progettato per la concorrenza.
Nel caso, se il tuo obbiettivo finale e' eseguire una serie di insert e 
update su varie tabelle, puoi:
aprire una transazione,
eseguire le operazioni che devi (usando le condizioni di where),
commitare.
Se anche uno tentasse di eseguire una modifica sui dati che stai 
toccando all'interno della transazione questi avrebbe in risposta un 
attesa o un errore (a causa dei lock).
Se invece fosse la transazione stessa ad essere in ritardo su un update 
o una insert causata da un altro processo essa fallirebbe nella sua 
totalita' causando un rollback.
Per evitare le insert puoi sempre usare lock sull'intera tabella e/o 
chiavi primarie.
L'unica cosa a cui stare attenti sono le condizioni di deadlock (piu' 
probabile con tanti utenti che usano questo meccanismo e con transazioni 
molto lunghe).
Ma potrei non avere capito il tuo problema.


 Ma potrei non avere capito il tuo problema.
Ok, e' tutto chiaro e noto quello che hai detto. Il problema risiede in
questo: in una sp vengono fatti (molti) controlli su varie tabelle (diciamo
A, B e C). Se i controlli sono ok, vengono fatte degli update/insert in B, C
e D.
Pertanto puo' succedere che se due client eseguono contemporaneamente la sp,
posso superare entrambi i controlli e arrivare alla fase di aggiornamento,
mentre in realta' se (correttamente) solo il primo facessi i dovuti
controlli e poi gli aggiornamenti, il secondo vedrebbe fallire i propri
controlli e non farebbe gli aggiornamenti (quindi non e' solo un problema di
lock durante gli update/insert).
Quindi, come mi hai consigliato, bisogna intervenire sugli isolation level.
Avevo pensato, leggendo la documentazione che mi hai indicato ad un:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; oppire meglio
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
all'inizio della sp.
Che ne dici?


 
La READ COMMITED e' il default quindi puoi anche non specificarlo.
Ho paura che nel tuo caso dovrai andare sul SERIALIZABLE.
Dipende se la procedura debba fallire nel caso in cui qualcuno apporti 
modifiche sulle tabella su cui vai ad eseguire i test (del punto 1).


Mumble...
ci sono diverse strade...
in primo luogo rifletti bene se il disegno dell'applicazione sia
effettivamente corretto e se, in caso contrario, potresti modificare
il comportamento.
IMHO... le strade percorribili sono 2 entrambi implicano l'utilizzo
di sistemi di serializzazioni
1 - lock sull'oggetto che ha necessità di essere serializzato, per
esempio gli oggetti sui quali devi effettuare l'update, ed eventuale
gestione delle eccezioni (lock nowait non aspetta ma solleva un 
eccezione che può essere gestita)
2 - dbms_lock (mi sembra il nome del pkg) ti permette di definire dei
meccanismi di serializzazione proprietari.
In ordine di preferenza 1 e 2... non utilizzare livelli di isolamento
differenti... diventa un casino e basta e sopratutto un bagno di sangue
in fase di debugging.
giorgio
