Newsgroup: it.comp.software.database
Titolo: Gestione dei locks: evitare deadlock e starvation

Salve a tutti, sto implementando un meccanismo di lock pessimistico su una
struttura ad albero.
La tabella che gestisce il lock è così definita:
LockType (1 = Inserimento, 2 = Modifica, 3 = Eliminazione)
CREATE TABLE Locks
(
 ID VARCHAR(32),
 LockType INTEGER,
 JobID VARCHAR(32),
 ObjectKey VARCHAR(32),
 SessionID VARCHAR(32),
 WaitFrom VARCHAR(32),
 WaitDate DATETIME,
 CONSTRAINT PK_Locks PRIMARY KEY (ID)
)
CREATE UNIQUE INDEX IDX_Locks ON Locks (LockType, JobID)
Un client per poter acquisire un lock deve verificare certe condizioni (in
base al tipo di lock che vuole acquisire), verificate queste condizioni
viene inserito un record che ne descrive il lock.
Per evitare situazioni di deadlock nel caso in cui il client1 voglia
bloccare un oggetto già bloccato dal client2, e a sua volta il client2
voglia ottenere un lock su un oggetto bloccato dal client1 ho pensato di
utilizzare un campo denominato "WaitFrom" nel quale si specifica che il lock
non è "effettivo" ma in attesa perchè occupato dal client specificato nel
valore del campo. Tale condizione evita in modo preventivo i deadlock nel
modo seguente:
Client1 ottiene un lock di modifica sull'oggetto A (viene effettuata INSERT
INTO Locks ('1','2','job1','A','sessione1',null,null))
Client2 ottiene un lock di modifica sull'oggetto B (viene effettuata INSERT
INTO Locks ('2','2','job1','B','sessione2',null,null))
Client1 ottiene un attesa per un lock di modifica sull'oggetto B  (viene
effettuata INSERT INTO LOCKS
('3','2','job1','B','sessione1','sessione2','01/01/2009 00:00:00')
Client2 vorrebbe mettersi in attesa per ottenere un lock sull'oggetto A ma
si accorge tramite la seguente query che ciò provocherebbe un deadlock,
quindi il lock fallisce immediatamente.
query di protezione contro i deadlock:
SELECT *
   FROM Locks L1
 WHERE (NOT SessionID = 'sessione2')
                AND ObjectKey = 'A'
                AND EXISTS (SELECT *
                                                   FROM Locks
                                                 WHERE SessionID = 'B' AND
WaitFrom  = L1.SessionID
                                               )
le condizioni di starvation cerco di gestirle tramite il campo WaitDate (le
più vecchie hanno priorità maggiore), ma non sono del tutto escluse poichè
potrebbe capitare che client1 è sempre quello più veloce ad acquisire i
locks e client2 venga sempre "buttato fuori" perchè un suo lock potrebbe
causare una situazione di deadlock.
Ho cercato in rete soluzioni che mi mettano "al sicuro" sia dai deadlock che
da starvation ma non ne ho trovate..
Qualche suggerimento?
Grazie

 Qualche suggerimento?
Stai cercando di fare una cosa difficilissima con un tool pensato
per altre cose.
Il dbms non e` l'ideale per implementare un meccanismo di
concorrenza, sia perche' ottimizzato per altre cose, sia perche'
ne ha gia' uno suo.
Se proprio vuoi usare il motore del dbms, cerca prima di
sfruttarne il suo usuale meccanismo di locking, facendolo
(parzialmente) sovrapporre al tuo.
Poi, bisognerebbe calcolare la correttezza dell'algoritmo
secondo il formalismo della teoria della concorrenza (r(1) w(1) etc).
Magari conoscendo le tue esigenze, e per quale scopo lo userai,
forse si concluderebbe che usare un linguaggio thread safe e` la
soluzione migliore...
bye 

 soluzione migliore...
la mia esigenza è molto semplice.. ho una struttura gerarchica tipo file 
system memorizzata all'interno del database, quello che voglio fare è 
implementare una gestione dei locks pessimistica, in modo ad esempio che se 
il client1 modifica il nodo A, un altro client2 non possa eliminarlo fino a 
quando client1 non ha terminato la modifica; oppure se client1 interisce un 
nodo B come figlio del nodo A, un altro client3 non possa inserire un nodo 
figlio di A che si chiami B perchè è già in fase di inserimento da parte del 
client1. Questo meccanismo di "controllo" penso si possa gestire tramite una 
tabella che implementi un meccanismo di  locking. Il problema che fino ad 
ora non ho risolto con la struttura presentata nel post precedente sono le 
condizioni eventuali di starvation, in quanto tale metodologia mi mette al 
sicuro solo da potenziali deadlock ma lascia aperte eventuali condizioni di 
starvation.
Esiste una metodologia di locking che eviti sia deadlock che starvation?
Grazie 

 che starvation?
Hum, ci sara` sempre la possibilita` che una query piu` recente
passi prima della transazione piu` vecchia.
C'e` un motivo valido per il quale la transazione non si avvia,
ed e` che non si sono verificate le condizioni che la
sbloccano e/o ci sono transazioni, che si suppone finiscano
prima, che la "sorpassano" (e questo e` buono per il sistema
nel suo complesso).
Un sistema viene considerato buono se ottengo un throughput
globale alto di transazioni/minuto; questa condizione e`
egualmente soddisfatta anche se la ns. transazione resta in
attesa ma 100 gli passano davanti.
Forse puoi pensare ad una priorita` forzata dopo X transazioni
che ti scavalcano; le nuove transazioni verrebbero accodate
dopo la transazione in attesa, il che pero' avrebbe il
potenziale per creare un ingolfamento anche maggiore...
Generalmente il tempo o cicli trascorsi costituiscono pessimi
fattori su cui basare le decisioni in ambiente concorrente;
algoritmi apparentemente validi sulla carta esibiscono
comportamenti deleteri sotto stress o in circostanze impreviste.
Non ti voglio scoraggiare, ma assicurati di sapere la portata
del lavoro che vai a fare.
bye