Поделиться через


sp_getapplock (Transact-SQL)

Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure

Размещает блокировку на ресурсе приложения.

Соглашения о синтаксисе Transact-SQL

Синтаксис

sp_getapplock
    [ [ @Resource = ] N'Resource' ]
    , [ @LockMode = ] 'LockMode'
    [ , [ @LockOwner = ] 'LockOwner' ]
    [ , [ @LockTimeout = ] LockTimeout ]
    [ , [ @DbPrincipal = ] N'DbPrincipal' ]
[ ; ]

Аргументы

[ @Resource = ] N'Ресурс

Строка, указывающая имя, определяющее ресурс блокировки. @Resource — nvarchar(255) с значением по умолчаниюNULL. Если строка ресурса длиннее nvarchar(255), значение усечено до nvarchar(255).

Приложение должно гарантировать уникальность имени ресурса. Указанное имя хэшируется внутренне в значение, которое может храниться в диспетчере блокировки SQL Server.

@Resource сравнивается с двоичными данными, поэтому учитывается регистр независимо от параметров сортировки текущей базы данных.

Примечание.

После того как произойдет блокировка приложения, только первые 32 символа могут быть получены в виде обычного текста; остаток будет хэширован.

[ @LockMode = ] 'LockMode'

Режим блокировки для определенного ресурса. @LockMode — varchar(32), без значения по умолчанию и является одним из следующих значений:

  • Shared
  • Update
  • IntentShared
  • IntentExclusive
  • Exclusive

Дополнительные сведения см. в режимах блокировки.

[ @LockOwner = ] 'LockOwner'

Владелец блокировки, который является значением @LockOwner при запросе блокировки. @LockOwner — varchar(32) с значением по умолчаниюTransaction. Значение также может быть Session. Если значение Transaction@LockOwner по умолчанию или указано явным образом, sp_getapplock необходимо выполнить из транзакции.

[ @LockTimeout = ] LockTimeout

Значение времени ожидания блокировки в миллисекундах. @LockTimeout имеет значение int, а значение по умолчанию совпадает со значением@@LOCK_TIMEOUT, возвращаемым . Значение -1 (по умолчанию) означает отсутствие периода ожидания (т. е. ожидание навсегда). Чтобы указать, что запрос на блокировку должен возвращать возвращаемый код -1 вместо ожидания блокировки, когда запрос не может быть предоставлен немедленно, укажите 0.

[ @DbPrincipal = ] N'DbPrincipal'

Роль пользователя, роли или приложения, которая имеет разрешения на объект в базе данных. @DbPrincipal — sysname с значением по умолчаниюpublic. Вызывающий объект функции должен быть членом database_principal, dbo или предопределенной ролью базы данных db_owner для успешного вызова функции. Значение по умолчанию является общедоступным.

Значения кода возврата

>= 0 (успешно) или < 0 (сбой).

Значение Результат
0 Блокировка была успешно предоставлена в синхронном режиме.
1 Блокировка была предоставлена успешно после снятия других несовместимых блокировок.
-1 Истекло время ожидания запроса блокировки.
-2 Запрос блокировки был отменен.
-3 Запрос блокировки был выбран как жертва взаимоблокировки.
-999 Указывает ошибку при проверке параметра или другую ошибку вызова.

Замечания

Блокировки, помещенные на ресурс, связаны либо с текущей транзакцией, либо с текущим сеансом. Блокировки, связанные с текущей транзакцией, снимаются, когда транзакция фиксируется или откатывается. Блокировки, связанные с сеансом, освобождаются при выходе сеанса. Когда сервер завершает работу по какой-либо причине, все блокировки освобождаются.

Созданный ресурс sp_getapplock блокировки создается в текущей базе данных для сеанса. Каждый ресурс блокировки определяется объединенными значениями следующих аргументов.

  • Идентификатор базы данных, содержащей ресурс блокировки.
  • Субъект базы данных, указанный в параметре @DbPrincipal .
  • Имя блокировки, указанное в параметре @Resource.

Только член субъекта базы данных, указанный в параметре @DbPrincipal, может получить блокировки приложений, указывающие этот субъект. Члены dbo и db_owner роли неявно считаются членами всех ролей.

Блокировки можно освободить явным образом с sp_releaseapplockпомощью . Когда приложение вызывает sp_getapplock несколько раз для одного ресурса блокировки, sp_releaseapplock необходимо вызвать одно и то же количество раз, чтобы освободить блокировку. При открытии блокировки с Transaction владельцем блокировки эта блокировка освобождается при фиксации или откате транзакции.

Если sp_getapplock вызывается несколько раз для одного ресурса блокировки, но режим блокировки, указанный в любом из запросов, не совпадает с существующим режимом, влияние на ресурс является объединением двух режимов блокировки. В большинстве случаев это значит, что режим блокировки повышается до более сильного режима блокировки, до существующего режима или до заново запрашиваемого режима. Этот более сильный режим блокировки удерживается до тех пор, пока блокировка в конечном итоге не будет освобождена, даже если вызовы выпуска блокировки происходят до этого времени.

Например, в следующей последовательности вызовов ресурс удерживается в режиме Exclusive, а не в режиме 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

Взаимоблокировка с блокировкой приложения не откатывает транзакцию, запрашивающую блокировку приложения. Любой откат, который может потребоваться как результат возвращаемого значения, должен быть сделан вручную. Поэтому рекомендуется включить проверку ошибок в код, чтобы при возврате определенных значений (например, -3ROLLBACK TRANSACTION ) инициируется или альтернативное действие.

Приведем пример:

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 использует текущий идентификатор базы данных для квалификации ресурса. Таким образом, если sp_getapplock выполняется даже с одинаковыми значениями параметров в разных базах данных, результатом является отдельная блокировка отдельных ресурсов.

Используйте динамическое sys.dm_tran_locks представление управления или системную sp_lock хранимую процедуру для проверки сведений о блокировке или с помощью SQL Server Profiler для отслеживания блокировок.

Разрешения

Необходимо быть членом роли public.

Примеры

Следующий пример помещает совмещаемую блокировку, связанную с текущей транзакцией, на ресурс Form1 в базе данных AdventureWorks2022.

USE AdventureWorks2022;
GO

BEGIN TRANSACTION;

DECLARE @result INT;

EXEC @result = sp_getapplock
    @Resource = 'Form1',
    @LockMode = 'Shared';

COMMIT TRANSACTION;
GO

В данном примере в качестве участника базы данных задается dbo.

BEGIN TRANSACTION;

EXEC sp_getapplock
    @DbPrincipal = 'dbo',
    @Resource = 'AdventureWorks2022',
    @LockMode = 'Shared';

COMMIT TRANSACTION;
GO