我有一个程序(usp_LoadCDRActivated
)调用另一个程序(usp_crs_LoadCDRsByBatch
)。 proc usp_crs_LoadCDRsByBatch
调用了另外六个过程,这些过程将数据从单个临时表加载到其他汇总表。我通过队列运行父proc(usp_LoadCDRActivated
)。
现在,当我启动队列时,总会出现死锁,因此会自动禁用队列的异常。
请帮我解决这个问题。
如果您想了解更多详情,请与我们联系。
以下是父程序......
ALTER procedure [dbo].[usp_LoadCDRActivated]
as
begin
set nocount on;
declare @h uniqueidentifier
, @messageTypeName sysname
, @messageBody varbinary(max)
, @xmlBody xml
, @batchID int
, @startTime datetime
, @finishTime datetime
, @execErrorNumber int
, @execErrorMessage nvarchar(2048)
, @xactState smallint
, @token uniqueidentifier;
begin transaction;
begin try;
receive top(1)
@h = [conversation_handle]
, @messageTypeName = [message_type_name]
, @messageBody = [message_body]
from [LoadCDRQueue];
if (@h is not null)
begin
if (@messageTypeName = N'DEFAULT')
begin
-- The DEFAULT message type is a procedure invocation.
-- Extract the name of the procedure from the message body.
--
select @xmlBody = CAST(@messageBody as xml);
select @batchID = @xmlBody.value(
'(//batch/batchID)[1]'
, 'int'
);
save transaction usp_LoadCDR_procedure;
select @startTime = GETUTCDATE();
begin try
exec usp_crs_LoadCDRsByBatch @batchID;
end try
begin catch
-- This catch block tries to deal with failures of the procedure execution
-- If possible it rolls back to the savepoint created earlier, allowing
-- the activated procedure to continue. If the executed procedure
-- raises an error with severity 16 or higher, it will doom the transaction
-- and thus rollback the RECEIVE. Such case will be a poison message,
-- resulting in the queue disabling.
--
select @execErrorNumber = ERROR_NUMBER(),
@execErrorMessage = ERROR_MESSAGE(),
@xactState = XACT_STATE();
if (@xactState = -1)
begin
rollback;
raiserror(N'Unrecoverable error in procedure usp_crs_LoadCDRsByBatch (%i): %i: %s', 16, 10,
@batchID, @execErrorNumber, @execErrorMessage);
end
else if (@xactState = 1)
begin
rollback transaction usp_LoadCDR_procedure;
end
end catch
select @finishTime = GETUTCDATE();
select @token = [conversation_id]
from sys.conversation_endpoints
where [conversation_handle] = @h;
if (@token is null)
begin
raiserror(N'Internal consistency error: conversation not found', 16, 20);
end
update [LoadCDRResults] set
[start_time] = @starttime
, [finish_time] = @finishTime
, [error_number] = @execErrorNumber
, [error_message] = @execErrorMessage
where [token] = @token;
if (0 = @@ROWCOUNT)
begin
raiserror(N'Internal consistency error: token not found', 16, 30);
end
end conversation @h;
end
else if (@messageTypeName = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
begin
end conversation @h;
end
else if (@messageTypeName = N'http://schemas.microsoft.com/SQL/ServiceBroker/Error')
begin
declare @errorNumber int
, @errorMessage nvarchar(4000);
select @xmlBody = CAST(@messageBody as xml);
with xmlnamespaces (DEFAULT N'http://schemas.microsoft.com/SQL/ServiceBroker/Error')
select @errorNumber = @xmlBody.value ('(/Error/Code)[1]', 'INT'),
@errorMessage = @xmlBody.value ('(/Error/Description)[1]', 'NVARCHAR(4000)');
-- Update the request with the received error
select @token = [conversation_id]
from sys.conversation_endpoints
where [conversation_handle] = @h;
update [LoadCDRResults] set
[error_number] = @errorNumber
, [error_message] = @errorMessage
where [token] = @token;
end conversation @h;
end
else
begin
raiserror(N'Received unexpected message type: %s', 16, 50, @messageTypeName);
end
end
commit;
end try
begin catch
declare @error int
, @message nvarchar(2048);
select @error = ERROR_NUMBER()
, @message = ERROR_MESSAGE()
, @xactState = XACT_STATE();
if (@xactState <> 0)
begin
rollback;
end;
raiserror(N'Error: %i, %s', 1, 60, @error, @message) with log;
end catch
结束
答案 0 :(得分:0)
我假设您有多个此过程并发运行的实例。我希望其中一个实例获得第一行的锁定,所有其他实例必须等待获取第一行的锁定。另一种方法是读取前n行并使用readpast锁定提示跳过锁定的行。