Condividi tramite


sp_getapplock (Transact-SQL)

Acquisisce un blocco su una risorsa di applicazione.

Icona di collegamento a un argomento Convenzioni della sintassi Transact-SQL

Sintassi

sp_getapplock [ @Resource = ] 'resource_name' ,
     [ @LockMode = ] 'lock_mode' 
     [ , [ @LockOwner = ] 'lock_owner' ] 
     [ , [ @LockTimeout = ] 'value' ]
     [ , [ @DbPrincipal = ] 'database_principal' ]
[ ; ]

Argomenti

  • [ @Resource= ] 'resource_name'
    Stringa contenente un nome che identifica la risorsa di blocco. L'applicazione deve garantire che il nome della risorsa sia univoco. Il nome specificato viene sottoposto internamente ad hashing per creare un valore che è possibile archiviare in Gestione blocchi di SQL Server. resource_name è di tipo nvarchar(255) e non prevede alcun valore predefinito. Se una stringa di risorsa ha una lunghezza maggiore di nvarchar(255), verrà troncata in nvarchar(255).

    Per resource_name viene eseguito un confronto binario ed è pertanto supportata la distinzione tra maiuscole e minuscole indipendentemente dalle impostazioni delle regole di confronto del database corrente.

    [!NOTA]

    Dopo l'acquisizione di un blocco a livello di applicazione, è possibile recuperare solo i primi 32 caratteri in testo normale. La parte rimanente viene sottoposta a hashing.

  • [ @LockMode= ] 'lock_mode'
    Modalità di blocco da acquisire per una particolare risorsa. lock_mode è di tipo nvarchar(32) e non prevede alcun valore predefinito. Il valore può essere uno dei seguenti, ovvero Shared, Update, IntentShared, IntentExclusive o Exclusive.

  • [ @LockOwner= ] 'lock_owner'
    Proprietario del blocco, ovvero il valore di lock_owner quando è stato richiesto il blocco. lock_owner è di tipo nvarchar(32). Il valore può essere Transaction (predefinito) o Session. Quando il valore di lock_owner è Transaction, per impostazione predefinita o specificato in modo esplicito, sp_getapplock deve essere eseguito in una transazione.

  • [ @LockTimeout= ] 'value'
    Valore di timeout del blocco espresso in millisecondi. Il valore predefinito corrisponde al valore restituito da @@LOCK_TIMEOUT. Per indicare che una richiesta di blocco deve restituire un errore anziché rimanere in attesa del blocco quando non può essere soddisfatta immediatamente, specificare 0.

  • [ @DbPrincipal= ] 'database_principal'
    Utente, ruolo o ruolo applicazione al quale sono state assegnate autorizzazioni per un oggetto di un database. Affinché la chiamata della funzione abbia esito positivo, è necessario che il chiamante sia un membro del ruolo predefinito del database database_principal, dbo o db_owner. Il valore predefinito è public.

Valori restituiti

>= 0 (esito positivo), or < 0 (esito negativo)

Valore

Risultato

0

Il blocco è stato concesso in modo sincrono.

1

Il blocco è stato concesso dopo il rilascio di altri blocchi incompatibili.

-1

La richiesta di blocco è scaduta.

-2

La richiesta di blocco è stata annullata.

-3

La richiesta di blocco è stata scelta come vittima del deadlock.

-999

Indica un errore di convalida di un parametro o un altro errore di chiamata.

Osservazioni

I blocchi acquisiti per una risorsa sono associati alla transazione o alla sessione corrente. I blocchi associati alla transazione corrente vengono rilasciati in corrispondenza del commit o del rollback della transazione. I blocchi associati alla sessione vengono rilasciati al termine della sessione. In caso di arresto del server per qualsiasi motivo, vengono rilasciati tutti i blocchi.

La risorsa di blocco creata da sp_getapplock è valida per il database corrente nella sessione corrente. Ogni risorsa di blocco viene identificata tramite la combinazione dei valori seguenti:

  • ID del database contenente la risorsa di blocco.

  • Entità di database specificata nel parametro @DbPrincipal.

  • Nome di blocco specificato nel parametro @Resource.

Solo un membro dell'entità di database specificata nel parametro @DbPrincipal può acquisire blocchi a livello di applicazione che specificano tale entità. I membri dei ruoli dbo e db_owner vengono considerati in modo implicito membri di tutti i ruoli.

È possibile rilasciare un blocco in modo esplicito tramite sp_releaseapplock. Se un'applicazione richiama sp_getapplock più volte per la stessa risorsa di blocco, per rilasciare il blocco è necessario richiamare sp_releaseapplock lo stesso numero di volte.

Se sp_getapplock viene chiamata più volte per una stessa risorsa di blocco ma la modalità di blocco specificata in una delle richieste è diversa da quella già esistente, verrà eseguita un'unione delle due modalità di blocco. Nella maggior parte dei casi la modalità di blocco viene promossa in base alla modalità che risulta più restrittiva tra quella esistente e quella nuova. Tale modalità viene quindi mantenuta fino al rilascio definitivo del blocco, anche se vengono eseguite chiamate di rilascio del blocco prima di tale momento. Nella sequenza di chiamate seguente, ad esempio, la risorsa viene mantenuta in modalità Exclusive anziché in modalità Shared.

USE AdventureWorks2012;
GO
BEGIN TRANSACTION;
DECLARE @result int;
EXEC @result = sp_getapplock @Resource = 'Form1', 
               @LockMode = 'Shared';
EXEC @result = sp_getapplock @Resource = 'Form1', 
               @LockMode = 'Exclusive';
EXEC @result = sp_releaseapplock @Resource = 'Form1';
COMMIT TRANSACTION;
GO

Un deadlock con un blocco a livello di applicazione non comporta il rollback della transazione che ha richiesto il blocco. Le eventuali operazioni di rollback richieste a causa del valore restituito devono essere eseguite in modo manuale. È pertanto consigliabile includere nel codice il controllo degli errori, in modo che venga avviata un'istruzione ROLLBACK TRANSACTION o un'azione alternativa se vengono restituiti valori specifici, ad esempio -3.

Esempio:

USE AdventureWorks2012;
GO
BEGIN TRANSACTION;
DECLARE @result int;
EXEC @result = sp_getapplock @Resource = 'Form1', 
               @LockMode = 'Exclusive';
IF @result = -3
BEGIN
    ROLLBACK TRANSACTION;
END
ELSE
BEGIN
    EXEC @result = sp_releaseapplock @Resource = 'Form1';
    COMMIT TRANSACTION;
END;
GO

In SQL Server per identificare la risorsa viene utilizzato l'ID del database corrente. Pertanto, se viene eseguita sp_getapplock su database diversi, anche se i valori dei parametri sono identici, vengono acquisiti blocchi separati su risorse separate.

Utilizzare la vista a gestione dinamica sys.dm_tran_locks o la stored procedure di sistema sp_lock per esaminare le informazioni di blocco oppure utilizzare SQL Server Profiler per monitorare i blocchi.

Autorizzazioni

È richiesta l'appartenenza al ruolo public.

Esempi

Nell'esempio seguente viene inserito un blocco condiviso, associato alla transazione corrente, nella risorsa Form1 del database AdventureWorks2012.

USE AdventureWorks2012;
GO
BEGIN TRAN;
DECLARE @result int;
EXEC @result = sp_getapplock @Resource = 'Form1', 
               @LockMode = 'Shared';
COMMIT TRAN;
GO

Nell'esempio seguente viene specificato dbo come entità di database.

BEGIN TRAN;
EXEC sp_getapplock @DbPrincipal = 'dbo', @Resource = 'AdventureWorks2012', 
     @LockMode = 'Shared';
COMMIT TRAN;
GO

Vedere anche

Riferimento

APPLOCK_MODE (Transact-SQL)

APPLOCK_TEST (Transact-SQL)

sp_releaseapplock (Transact-SQL)