vto*_*ola 3 sql-server multithreading synchronization locking sql-server-2005
多个Web服务器访问SQL Server以获取数字代码,当此代码不存在时,它必须由SQL Server自动生成.
我需要确保即使两个并发调用进入并且代码不存在,也只创建一个代码,并且两个调用都返回相同的代码.所以我必须做这样的事情:
begin lock
if code exists
return code
else
generate code
return code
end lock
Run Code Online (Sandbox Code Playgroud)
我一直在阅读关于隔离级别和表锁定的一些内容,但我对这一切都很糟糕.首先,我认为SERIALIZABLE隔离级别是我需要的,但显然它不是.
那么,你将如何在TSQL中实现"锁定"?
非常感谢.
更新:
当我尝试使用此示例设置可序列化级别时出现此错误:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE get_code
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
select code from codes where granted is null;
END
GO
Run Code Online (Sandbox Code Playgroud)
消息1018,级别15,状态1,过程get_code,第4行'SERIALIZABLE'附近的语法不正确.如果这是作为表提示的一部分,则现在需要A WITH关键字和括号.有关正确的语法,请参阅SQL Server联机丛书.消息102,级别15,状态1,行5'END'附近的语法不正确.
这是什么意思?
SERIALIZABLE是锁定的隔离级别,而不是信号量.
在这种情况下它不起作用你所做的只是在TXN的末尾保持读锁定,这不会阻止另一个进程进入代码读取.
您需要在事务模式下使用sp_getapplock.您可以将其配置为等待,立即炸弹等:由您决定
这是基于我的包含TRY CATCH ROLLBACK模式的嵌套存储过程的模板?
ALTER PROCEDURE get_code
AS
SET XACT_ABORT, NOCOUNT ON
DECLARE @starttrancount int, @result int;
BEGIN TRY
SELECT @starttrancount = @@TRANCOUNT
IF @starttrancount = 0 BEGIN TRANSACTION
EXEC @result = sp_getapplock 'get_code', 'Exclusive', 'Transaction', 0
IF @result < 0
RAISERROR('INFO: One at a time please`!', 16, 1);
[...Perform work...]
IF @starttrancount = 0
COMMIT TRANSACTION
ELSE
EXEC sp_releaseapplock 'get_code';
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 AND @starttrancount = 0
ROLLBACK TRANSACTION
RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6129 次 |
最近记录: |