Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL锁定未正确实现_Sql_Sql Server_Sql Server 2008_Tsql_Stored Procedures - Fatal编程技术网

SQL锁定未正确实现

SQL锁定未正确实现,sql,sql-server,sql-server-2008,tsql,stored-procedures,Sql,Sql Server,Sql Server 2008,Tsql,Stored Procedures,我在一个过程中实现了一个SQL tablockx锁定。当它在一台服务器上运行时工作正常。但是当请求来自两台不同的服务器时,会出现重复的policyNumber declare @plantype varchar(max), @transid varchar(max), @IsStorySolution varchar(10), @outPolicyNumber varchar(max) output, @status int output -- 0 mean error and 1 means

我在一个过程中实现了一个SQL tablockx锁定。当它在一台服务器上运行时工作正常。但是当请求来自两台不同的服务器时,会出现重复的policyNumber

declare @plantype varchar(max),
@transid varchar(max),
@IsStorySolution varchar(10),
@outPolicyNumber varchar(max) output,
@status int output  -- 0 mean error and 1 means success
)
as
begin

BEGIN TRANSACTION

Declare @policyNumber varchar(100);
Declare @polseqid int;

-- GET POLICY NUMBER ON THE BASIS OF STORY SOLUTION..
IF (UPPER(@IsStorySolution)='Y')
BEGIN
select top 1 @policyNumber=Policy_no  from PLAN_POL_NO with (tablockx, holdlock) where policy_no like '9%' 
and pol_id_seq is null and status='Y';
END


ELSE
BEGIN
select top 1 @policyNumber=pp.Policy_no  from PLAN_POL_NO pp with (tablockx, holdlock) ,PLAN_TYP_MST pt where pp.policy_no  like PT.SERIES+'%'
and pt.PLAN_TYPE in (''+ISNULL(@plantype,'')+'') and pol_id_seq is null and pp.status='Y' 
END

-- GET POL_SEQ_ID NUMBER



select @polseqid=dbo.Sequence();



--WAITFOR DELAY '00:00:03';


set @policyNumber= ISNULL(@policyNumber,'');

-- UPDATE POLICY ID INFORMATION...

Update PLAN_POL_NO  set status='N',TRANSID =@transid , POL_ID_SEQ=ISNULL(@polseqid,0) where Policy_no =@policyNumber 

set @outPolicyNumber=@policyNumber;

if(@@ERROR<>0) begin GOTO Fail end

COMMIT Transaction
set @status=1;
return;
Fail:
If @@TRANCOUNT>0
begin
Rollback transaction
set @status=0;
return; 

您面临的问题是,并发请求都从表dbo.PLAN\u POL\u NO中获取相同的POL\u ID\u SEQ

您的问题有多种解决方案,但我可以想出两种可能对您有所帮助且不需要进行任何/小的代码更改的解决方案:

使用更高的事务隔离级别而不是表提示。 在存储过程中,可以使用以下各项:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
这将确保在SP块期间读取/修改的任何数据在事务上是一致的,并避免幻象读取、重复记录等。这可能会造成更高的死锁,如果在整个应用程序中大量查询/更新这些表,您可能会遇到一系列新的问题

确保只有在序列未更改的情况下才能成功更新dbo.PLAN_POL_NO。如果它已更改,则出错如果它已更改,则表示并发事务已获得ID并首先完成 大概是这样的:

Update dbo.PLAN_POL_NO 
SET    status      ='N',
       TRANSID     = @transid,
       POL_ID_SEQ  = ISNULL(@polseqid,0)
WHERE Policy_no = @policyNumber
      AND POL_ID_SEW = @polseqid - 1

IF @@ROWCOUNT <> 1
BEGIN
   -- Update failed, error out and let the SP rollback the transaction
END
函数中的WITH HOLDLOCK选项可能就足够了

第一个查询中的保持锁可能应用于行或页级别,但不包括函数中查询的感兴趣行


但是,该功能不可靠,因为它不是独立的。我希望重新设计它,这样序列可以在返回之前生成并获取序列号。当前的设计充其量是脆弱的。

您应该像使用存储过程Ctrl+K一样将函数格式化为代码。我试图编辑您的帖子,但网站无法识别这些更改。好的,我会这样做……请提供问题的解决方案。我需要更多信息来帮助您。存储过程调用如何来自两个独立的服务器?您是否错误地发送了两次相同的请求?或者你的意思是冲突是由来自两个独立服务器的两个独立请求引起的?事实上,我有一个sql环境,在这个环境中我编写了一个程序。因此,当一个请求只来自一个服务器时,在UAT中处理得很好。但当并发请求同时来自两个不同的服务器时,就会出现这个问题。我注意到的第一件事是,您在Fail:block中缺少了一个端点。我注意到的第二件事是,您不需要单独的SET命令来处理ISNULL,您可以在select语句中自己完成。除此之外,您的代码似乎应该正常工作?我的朋友建议的解决方案是这样的:从带有行锁的PLAN_POL_no中选择top 1@policyNumber=ISNULLPolicy_no,其中policy_no如'9%'和POL_id_seq为null,status='Y'按Newid排序;请建议
Update dbo.PLAN_POL_NO 
SET    status      ='N',
       TRANSID     = @transid,
       POL_ID_SEQ  = ISNULL(@polseqid,0)
WHERE Policy_no = @policyNumber
      AND POL_ID_SEW = @polseqid - 1

IF @@ROWCOUNT <> 1
BEGIN
   -- Update failed, error out and let the SP rollback the transaction
END