sp_getapplock (Transact-SQL)

Si applica a:SQL Server database SQL di Azure Istanza gestita di SQL di Azure

Acquisisce un blocco su una risorsa di applicazione.

Convenzioni di 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 all'hashing in un valore che può essere archiviato nella gestione blocchi di SQL Server. resource_name è nvarchar(255) senza impostazione predefinita. Se una stringa di risorsa è più lunga di nvarchar(255),verrà troncata a nvarchar(255).

resource_name viene confrontato in modo binario e pertanto fa 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 è varchar(32) e non ha alcun valore predefinito. Il valore può essere uno dei seguenti: Shared, Update, IntentShared, IntentExclusive o Exclusive. Per altre informazioni, vedere Modalità di blocco.

[ @LockOwner= ] 'lock_owner'
Proprietario del blocco, ovvero il valore di lock_owner al momento della richiesta del blocco. lock_owner è varchar(32). Il valore può essere Transaction (impostazione predefinita) o Session. Quando il valore lock_owner è Transaction, per impostazione predefinita o specificato in modo esplicito, sp_getapplock deve essere eseguito dall'interno di una transazione.

[ @LockTimeout= ] 'value'
Valore di timeout del blocco espresso in millisecondi. Il valore predefinito corrisponde al valore restituito da @@LOCK_TIMEOUT. Il valore -1 (predefinito) corrisponde a nessun periodo di timeout, ovvero a un'attesa infinita. Per indicare che una richiesta di blocco deve restituire un codice restituito pari a -1 anziché attendere il blocco quando la richiesta non può essere concessa immediatamente, specificare 0.

[ @DbPrincipal= ] 'database_principal'
Utente, ruolo o ruolo applicazione al quale sono state assegnate autorizzazioni per un oggetto di un database. Il chiamante della funzione deve essere membro di database_principal, dbo o del ruolo predefinito del database db_owner per chiamare correttamente la funzione. Il valore predefinito è public.

Valori del codice restituito

>= 0 (esito positivo) o < 0 (errore)

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 quando la sessione viene disconnessa. Quando il server viene arrestato per qualsiasi motivo, tutti i blocchi vengono rilasciati.

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 @DbPrincipal parametro .

  • 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. Quando un blocco viene aperto con il proprietario del Transaction blocco, tale blocco viene rilasciato quando viene eseguito il commit o il rollback della transazione.

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. Questa modalità di blocco più forte viene mantenuta fino al rilascio del blocco. Nella sequenza di chiamate seguente, ad esempio, la risorsa viene mantenuta in modalità Exclusive anziché in modalità Shared.

USE AdventureWorks2022;  
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.

Ecco un esempio:

USE AdventureWorks2022;  
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  

SQL Server usa l'ID del database corrente per qualificare la risorsa. Pertanto, se si esegue sp_getapplock su database diversi, vengono acquisiti blocchi separati su risorse diverse anche se i valori dei parametri sono identici.

Usare la sys.dm_tran_locks vista a gestione dinamica o la stored procedure di sistema sp_lock per esaminare le informazioni di blocco o usare 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 AdventureWorks2022.

USE AdventureWorks2022;  
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 = 'AdventureWorks2022',   
     @LockMode = 'Shared';  
COMMIT TRAN;  
GO  

Vedi anche

APPLOCK_MODE (Transact-SQL)
APPLOCK_TEST (Transact-SQL)
sp_releaseapplock (Transact-SQL)