sp_getapplock (Transact-SQL)

适用于: SQL Server Azure SQL 数据库 Azure SQL 托管实例

对应用程序资源设置锁。

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'

要为特定资源获取的锁定模式。 @LockModevarchar(32),没有默认值,并且是以下值之一:

  • Shared
  • Update
  • IntentShared
  • IntentExclusive
  • Exclusive

有关详细信息,请参阅 锁定模式

[ @LockOwner = ] 'LockOwner'

锁的所有者,这是 请求锁时@LockOwner 值。 @LockOwner为 varchar(32),默认值为 Transaction. 该值也可以是 Session默认情况下或显式指定@LockOwnerTransaction时,sp_getapplock必须从事务内执行。

[ @LockTimeout = ] LockTimeout

锁定超时值(以毫秒为单位)。 @LockTimeout为 int,默认值与返回@@LOCK_TIMEOUT的值相同。 值 -1 (默认值)表示没有超时期限(即,永远等待)。 若要指示锁请求应返回返回代码, -1 而不是在无法立即授予请求时等待锁,请指定 0

[ @DbPrincipal = ] N'DbPrincipal'

对数据库中对象具有权限的用户、角色或应用程序角色。 @DbPrincipal为 sysname,默认值为 public. 函数的调用方必须是database_principal、dbodb_owner固定数据库角色的成员才能成功调用函数。 默认值为 公共

返回代码值

>= 0 (成功),或 < 0 (失败)。

结果
0 锁已同时成功授予。
1 在等待释放其他不兼容锁后成功授予锁。
-1 锁请求超时。
-2 锁请求被取消。
-3 选择锁请求作为死锁牺牲品。
-999 指示参数验证或其他调用错误。

注解

对资源设置的锁与当前事务或当前会话相关联。 当事务提交或回滚时,将释放与当前事务相关联的锁。 注销会话时会释放与会话关联的锁。服务器出于任何原因关闭时,将释放所有锁。

创建的 sp_getapplock 锁资源是在会话的当前数据库中创建的。 每个锁资源都由下列值的组合值进行标识:

  • 包含锁资源的数据库的数据库 ID。
  • @DbPrincipal 参数中指定的数据库主体。
  • @Resource 参数中指定的锁名。

只有@DbPrincipal参数中指定的数据库主体的成员才能获取指定该主体的应用程序锁。 dbodb_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 使用当前数据库 ID 来限定资源。 因此,如果 sp_getapplock 执行了相同的参数值,即使对不同的数据库使用相同的参数值,结果也会对单独的资源进行单独的锁。

sys.dm_tran_locks使用动态管理视图或sp_lock系统存储过程检查锁信息,或使用 SQL Server Profiler 监视锁。

权限

要求 公共 角色具有成员身份。

示例

下面的示例对 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