Concorrenza dei cursori (Motore di database)
Microsoft SQL Server supporta quattro opzioni di concorrenza per i cursori del server:
READ_ONLY
OPTIMISTIC WITH VALUES
OPTIMISTIC WITH ROW VERSIONING
SCROLL LOCKS
READ_ONLY
Gli aggiornamenti posizionati eseguiti attraverso il cursore non sono consentiti e sulle righe del set di risultati non viene mantenuto attivo alcun blocco.OPTIMISTIC WITH VALUES
Il controllo della concorrenza ottimistica è una componente standard della teoria del controllo delle transazioni. Il controllo della concorrenza ottimistica viene utilizzato quando la possibilità che un secondo utente o processo aggiorni una riga nell'intervallo che intercorre tra l'apertura del cursore e l'aggiornamento della riga è minima. Quando un cursore viene aperto con questa opzione, i blocchi delle righe sottostanti non vengono mantenuti attivi, con una conseguente ottimizzazione della velocità effettiva. Se l'utente tenta di modificare una riga, i valori correnti della riga vengono confrontati con quelli recuperati durante l'ultima operazione di recupero. Se uno dei valori è stato modificato, nel server viene dedotto che la riga è già stata aggiornata da un altro utente o processo e viene restituito un errore. Se invece i valori sono identici, il server esegue la modifica.Quando questa opzione di concorrenza è impostata, l'utente o il programmatore deve gestire la visualizzazione occasionale di un errore che segnala che la riga è stata modificata da un altro utente. In genere, quando un'applicazione riceve un errore di questo tipo, viene aggiornato il cursore, vengono recuperati i nuovi valori e viene quindi consentito all'utente di decidere se apportare o meno la modifica ai nuovi valori. In SQL Server 6.5 e versioni precedenti le colonne di tipo text, ntext e image non vengono utilizzate per i confronti di concorrenza.
OPTIMISTIC WITH ROW VERSIONING
Questa opzione per il controllo della concorrenza ottimistica è basata sul controllo delle versioni delle righe. Con il controllo delle versioni delle righe, è necessario che per la tabella sottostante sia disponibile un identificatore di versione utilizzabile dal server per determinare se la riga è stata modificata dopo la lettura nel cursore. In SQL Server tale funzionalità viene implementata tramite il tipo di dati timestamp, ovvero un numero binario che indica la sequenza relativa delle modifiche apportate al database. Ogni database è caratterizzato da un valore timestamp globale specificato in **@@**DBTS. A ogni modifica di una riga che include una colonna di tipo timestamp, SQL Server archivia il valore **@@**DBTS corrente nella colonna di tipo timestamp e quindi incrementa **@@**DBTS. Se la tabella include una colonna di tipo timestamp, i valori timestamp vengono portati a livello di riga. Il server è quindi in grado di confrontare il valore timestamp corrente di una riga con quello archiviato durante l'ultima operazione di recupero per determinare se la riga è stata aggiornata. Nel server non è necessario eseguire il confronto dei valori di tutte le colonne, ma solo dei valori della colonna di tipo timestamp. Se un'applicazione richiede la concorrenza ottimistica con il controllo delle versioni delle righe in una tabella priva di colonne di tipo timestamp, per impostazione predefinita il cursore ripristina il controllo della concorrenza ottimistica basato sui valori.Nota
Per i cursori aperti in origini dati remote, non sono supportati gli aggiornamenti tramite il cursore se nell'origine remota non è inclusa una colonna di tipo timestamp.
SCROLL LOCKS
Questa opzione implementa il controllo della concorrenza pessimistica, in base al quale l'applicazione tenta di bloccare le righe di database sottostanti nel momento in cui vengono lette nel set di risultati del cursore. Quando si utilizzano cursori del server, sulla riga viene impostato un blocco di aggiornamento nel momento in cui viene letta nel cursore. Se il cursore è aperto in una transazione, il blocco di aggiornamento della transazione viene mantenuto attivo fino al commit o al rollback della transazione. Il blocco del cursore viene eliminato in corrispondenza del recupero della riga successiva. Se il cursore è stato aperto all'esterno di una transazione, il blocco viene eliminato durante l'operazione di recupero della riga successiva. Per ottenere il controllo completo della concorrenza pessimistica, è pertanto necessario che in una transazione sia aperto un cursore. Un blocco di aggiornamento impedisce l'acquisizione di un blocco di aggiornamento o di un blocco esclusivo tramite altre attività, impedendo in tal modo l'aggiornamento della riga. Un blocco di aggiornamento non ha tuttavia alcun effetto su un blocco condiviso, ovvero non impedisce la lettura delle righe tramite altre attività a meno che queste non richiedano anch'esse la lettura con blocco di aggiornamento.
Blocchi di scorrimento
Queste opzioni di concorrenza dei cursori possono generare blocchi di scorrimento a seconda degli hint di blocco specificati nell'istruzione SELECT nella definizione del cursore. I blocchi di scorrimento vengono acquisiti in ogni riga mediante un'operazione di recupero e vengono mantenuti attivi fino all'operazione di recupero successiva o fino alla chiusura del cursore, a seconda di quale dei due eventi si verifica per primo. Durante l'operazione di recupero successiva, il server acquisisce i blocchi di scorrimento per le righe recuperate durante l'operazione in corso, quindi rilascia i blocchi per le righe recuperate nel corso dell'operazione precedente. I blocchi di scorrimento sono indipendenti dai blocchi delle transazioni e possono persistere anche dopo l'esecuzione del commit o del rollback. Se l'opzione per la chiusura dei cursori durante il commit è disattivata, quando si esegue l'istruzione COMMIT i cursori aperti non vengono chiusi e i blocchi di scorrimento vengono mantenuti attivi anche dopo il commit per mantenere l'isolamento dei dati recuperati.
Il tipo di blocco di scorrimento acquisito varia a seconda dell'opzione di concorrenza del cursore e degli hint di blocco specificati nell'istruzione SELECT del cursore.
Nota
I blocchi di scorrimento sono supportati solo per i cursori dinamici e gestiti da keyset.
Hint di blocco |
Read only |
Optimistic with values |
Optimistic with row versioning |
Blocco |
---|---|---|---|---|
Nessun hint |
- |
- |
- |
Aggiornamento |
NOLOCK* |
- |
- |
- |
- |
HOLDLOCK |
- |
- |
- |
Aggiornamento |
UPDLOCK |
- |
- |
- |
Aggiornamento |
TABLOCKX |
- |
- |
- |
Aggiornamento |
Tutti gli altri |
- |
- |
- |
Aggiornamento |
* Quando si specifica l'hint NOLOCK, la tabella in cui è specificato diventa di sola lettura tramite il cursore.
Impostazione delle opzioni di concorrenza dei cursori
Le opzioni di concorrenza vengono specificate in modo diverso a seconda dell'ambiente del cursore:
Cursori Transact-SQL
Specificare le parole chiave READ_ONLY, SCROLL_LOCK e OPTIMISTIC nell'istruzione DECLARE CURSOR. La parola chiave OPTIMISTIC specifica la concorrenza ottimistica con il controllo delle versioni delle righe. I cursori Transact-SQL non supportano l'opzione di concorrenza ottimistica con valori.
Applicazioni ADO
Specificare adLockReadOnly, adLockPessimistic, adLockOptimistic o adLockBatchOptimistic nella proprietà LockType di un oggetto Recordset.
Applicazioni ODBC
Impostare l'attributo di istruzione SQL_ATTR_CONCURRENCY su SQL_CONCUR_READ_ONLY, SQL_CONCUR_ROWVER, SQL_CONCUR_VALUES o SQL_CONCUR_LOCK.