我需要在我的应用程序中实现一个锁定方案。如果用户尚未锁定,则用户只能打开对话框/表单。另一方面,如果当前没有对话框,则只能设置锁定,该锁定对应于该锁定。
到目前为止我的方法: 我有一个带有列lockname的sql server表tbl_lock,我在那里维护锁和一个表tbl_dialog(user,dialogname),每当用户打开一个对话框时我就会创建一行。
要创建锁,我会执行以下操作: 1)开始交易 2)选择*来自tbl_dialog并使用(SERIALIZABLE)其中dialogname = @ somename 3)如果prio select没有返回记录,则在tbl_lock中插入对话框@somename的锁记录 4)提交交易
问题是,我还想阻止有人试图在其他用户尝试设置锁定时打开对话框。我可以重复上面的4个步骤并选择带有serializable的tbl_lock并在tbl_dialog中插入一条记录,但我担心如果2个并发事务执行步骤,我会遇到死锁,从而同时锁定表tbl_dialog和tbl_lock。
我可以一次锁定第2步中的两个表吗?有没有更聪明的方法来解决这个问题?
最诚挚的问候, 的Sascha
编辑: 根据Bogdan的评论,我将实施以下SP来设置锁定:
Create procedure CreateLock
@dialogname nvarchar(10),
@lockname nvarchar(10)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @result int;
DECLARE @locksuccess int = 0;
begin tran;
EXEC @result = sp_getapplock @Resource = 'myapplockmanagement', @LockMode = 'Exclusive', @LockTimeout=3000;
if @result>=0
BEGIN
-- Ensure no user has opened the dialog @lockname
if not EXISTS(select 1 from tbl_dialog where dialogname=@dialogname)
BEGIN
if not EXISTS(select 1 from tbl_lock where lockname=@lockname)
BEGIN
insert into tbl_lock (lockname) values (@lockname);
set @locksuccess = 1;
END
END
commit;
END
ELSE
BEGIN
rollback;
END
return @locksuccess;
END
如果我正确理解sp_getapplock,myapplockmanagement将被独占锁定,从而锁定所有其他线程。如果可以获取应用程序锁定,我可以安全地检查我的tbl_dialog并最终在tbl_lock中插入一个新行,对吗?
所以下一个Procdure将是:
Create procedure RegisterDialogUsage
@dialogname nvarchar(10),
@lockname nvarchar(10)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @result int;
DECLARE @registersuccess int = 0;
begin tran;
EXEC @result = sp_getapplock @Resource = 'myapplockmanagement', @LockMode = 'Exclusive', @LockTimeout=3000;
if @result>=0
BEGIN
-- Ensure that no lock is set.
if not EXISTS(select 1 from tbl_lock where lockname=@lockname)
BEGIN
insert into tbl_dialog (dialogname) values (@dialogname);
set @registersuccess = 1;
END
commit;
END
ELSE
BEGIN
rollback;
END
return @registersuccess;
END
所以,如果我没有弄错的话,这两个SP完全按照我的意愿行事:
是吗? (用于删除tbl_lock和tbl_dialog中的条目的相应SP必须实现两个......)
的Sascha