1) Ho una form con una griglia che carico con con un recordset cosi'
impostato:
- CursorLocation = adUseClient
- CursorType = adOpenForwardOnly
- LockType = adLockReadOnly
la query viene eseguita su una vista
2) Con il doppio click su un elemento della griglia seleziono in modo
esclusivo quel record impostando il recordset in questo modo:
- CursorLocation = adUseServer
- CursorType = adOpenKeyset
- LockType = adLockPessimistic
avvio la transizione .BeginTrans
la query viene eseguita sulla tabella "fisica", non sulla vista
Una volta eseguita la query all'operatore viene visualizzata una form
dove puo' modificare i valori definiti dall'applicazione.
A questo punto se da un altro PC, si cerca di richiamare la form al
punto 1 (la griglia) si riceve il seguente messaggio:
Timeout della richiesta di blocco. Numero -2147217871
Mi domando e chiedo, sperando una volta per tutte di capirne il
funzionamento, ma come gestisce il lock del record SQL.
Grazie e ciao,
LittleWave
Hai lockato in modo pessimistico un record e quindi il record ha un lock
esclusivo per tutta la durata delle operazioni di edit (anche ore se
l'operatore se ne va in giro lasciando la maschera aperta...).
Mi pare naturale che se da un'altra connessione (un altro PC nel tuo caso)
cerchi di recuperare anche quel record, la query (che sia una vista o acceda
direttamente alla tabella non fa nessuno differenza) si blocchi fin tanto
che l'operatore di cui sopra non si � deciso di concludere le operazioni di
edit.
Ma a te che serve fare, e che versione di SQL Server stai usando?
E' proprio quello che capita spesso........
> Mi pare naturale che se da un'altra connessione (un altro PC nel tuo caso)
> cerchi di recuperare anche quel record, la query (che sia una vista o acceda
> direttamente alla tabella non fa nessuno differenza) si blocchi fin tanto
> che l'operatore di cui sopra non si è deciso di concludere le operazioni di
> edit.
Quando mi scrivi "Mi pare naturale che se da un'altra......." mi
chiedo perche' naturale?
Se sto accedendo a quel "record" in SOLA lettura perche' non ci fai
accedere?
> Ma a te che serve fare
Vorrei accedere, in lettura, anche a quei records che sono in lock.
>, e che versione di SQL Server stai usando?
La versione di SQL Server e' la 2005 SP2.
Grazie per la risposta, ciao,
LittleWave
> Quando mi scrivi "Mi pare naturale che se da un'altra......." mi
> chiedo perche' naturale?
> Se sto accedendo a quel "record" in SOLA lettura perche' non ci fai
> accedere?
>
Il livello di isolamento di default (read commited, vedi:
http://msdn.microsoft.com/it-it/library/ms173763(SQL.90).aspx
anche se in italiano non � che sia proprio chiaro...
) non permette di leggere dati che sono ancora sotto transazione.
> Vorrei accedere, in lettura, anche a quei records che sono in lock.
> La versione di SQL Server e' la 2005 SP2.
>
Hai due strade, o nella query che ti estrae i dati per la sola
visualizzazione usi l'hint nolock per "fregartene" dei lock piazzati da
altre connessioni che stanno bloccando le righe dove � in corso l'editing:
select * from tuaQuery with (nolock) where ...
(vedi http://msdn.microsoft.com/it-it/library/ms187373(SQL.90).aspx)
Ma in questo modo la tua query pu� recuperare dati che sono ancora in fase
di aggiornamento (per esempio, se qualcuno su una riga che � sotto
transazione ti ha aggiornato solo il cognome e non ancora il nome, la tua
query ti restituir� quella riga con il cognome nuovo e il nome vecchio).
Oppure un'altra soluzione, credo pi� robusta, che puoi adottare visto che
usi SQL 2005, � quella di impostare l'opzione READ_COMMITTED_SNAPSHOT a ON
sul tuo database e *NON* usare l'hint nolock nella query.
In questo modo l'accesso in lettura ad una riga che � ancora in fase di
aggiornamento recuperer� la versione precedente della stessa riga, cio� le
versione "vecchia" che sta subendo le modifiche. Nell'esempio di prima, la
tua query ti restituir� il cognome e il nome vecchi, e non il "misto mare"
causato dall'uso dell'hint nolock.
Nel primo link che ti ho indicato trovi spiegato come funziona l'opzione
read_commited_snapshot un po' pi� in dettaglio.
Tu qui stai chiedendo (i.e. adLockPessimistic) di bloccarlo a chiunque
(+ o -)... non puoi lamentartene poi!!!
E comunque è sbagliato; devi:
1) portarlo sul form con una select di sola lettura id est *NON*
loccato
2) attendere che l'Utente si faccia i suoi porci comodi
3) alla conferma controllare che il record sia rimasto lo stesso
4) se il 3 è verificato aggiornare le informazioni
La differenza con il tuo, sostanziale, è che si locca dopo, per i
nanotempo che serve all'aggironamento
Grazie della esaustiva risposta, ho provato, su un DB di test, la
seconda soluzione che mi hai proposto e sembra funzionare
correttamente, perlomeno non sono piu' riuscito a replicare l'anomalia
segnalata in precedenza.
Grazie di nuovo, ciao,
LittleWave
Hai perfettamente ragione, avevo pensato anche a questa soluzione ma
sono rimasto sull'altra (soluzione) per la difficolta' (scrivere
dell'altro codice :-).....) di controllare che il record sia rimasto
lo stesso, il punto 3 che mi hai segnalato.
In ogni caso la soluzione potrebbe essere poco gradita all'utente
finale, in quanto una volta che ha apportato le modifiche ai campi
presenti nella form, che potrebbero anche essere tanti e complessi,
potrebbe poi essere costretto a reinserirli in quanto un altro utente
nel frattempo ha modificato anche un solo valore sullo stesso record.
Grazie, ciao,
LittleWave