Sql 有时仅从一个SP获取请求超时?
我有很多存储过程。但有时我只收到此SP的请求超时Sql 有时仅从一个SP获取请求超时?,sql,tsql,sql-server-2008-r2,Sql,Tsql,Sql Server 2008 R2,我有很多存储过程。但有时我只收到此SP的请求超时 ALTER PROCEDURE [dbo].[Insertorupdatedevicecatalog] (@OS NVARCHAR(50) ,@UniqueID VARCHAR(500) ,@Longitude FLOAT ,@Latitude
ALTER PROCEDURE [dbo].[Insertorupdatedevicecatalog]
(@OS NVARCHAR(50)
,@UniqueID VARCHAR(500)
,@Longitude FLOAT
,@Latitude FLOAT
,@Culture VARCHAR(10)
,@Other NVARCHAR(200)
,@IPAddress VARCHAR(50)
,@NativeDeviceID VARCHAR(50))
AS
BEGIN
SET NOCOUNT ON;
DECLARE @TranCount INT;
SET @TranCount = @@TRANCOUNT;
DECLARE @OldUniqueID VARCHAR(500) = ''-1'';
SELECT @OldUniqueID = [UniqueID] FROM DeviceCatalog WHERE (@NativeDeviceID != '''' AND [NativeDeviceID] = @NativeDeviceID);
BEGIN TRY
IF @TranCount = 0
BEGIN TRANSACTION
ELSE
SAVE TRANSACTION Insertorupdatedevicecatalog;
DECLARE @Geo GEOGRAPHY = geography::STGeomFromText(''POINT('' + CONVERT(VARCHAR(100), @Longitude) + '' '' + CONVERT(VARCHAR(100), @Latitude) + '')'', 4326);
IF EXISTS(SELECT 1 FROM DeviceCatalog WHERE [UniqueID] = @UniqueID)
BEGIN
DECLARE @OldGeo GEOGRAPHY
,@OldCity NVARCHAR(100)
,@OldCountry NVARCHAR(100)
,@OldAddress NVARCHAR(100);
SELECT @OldGeo = [LastUpdatedLocationFromJob]
,@OldCity = [City]
,@OldCountry = [Country]
,@OldAddress = [Address]
FROM DeviceCatalog
WHERE [UniqueID] = @UniqueID;
UPDATE DeviceCatalog
SET [OS] = @OS
,[Location] = @Geo
,[Culture] = @Culture
,[Other] = @Other
,[IPAddress] = @IPAddress
WHERE [UniqueID] = @UniqueID;
IF (@OldGeo IS NULL OR @OldAddress IS NULL OR @OldCity IS NULL OR @OldCountry IS NULL OR ISNULL(@Geo.STDistance(@OldGeo) / 1000,0) > 50)
BEGIN
UPDATE DeviceCatalog
SET [Lastmodifieddate] = Getdate()
WHERE [UniqueID] = @UniqueID;
END
END
ELSE
BEGIN
INSERT INTO DeviceCatalog
([OS]
,[UniqueID]
,[Location]
,[Culture]
,[Other]
,[IPAddress]
,[NativeDeviceID])
VALUES (@OS
,@UniqueID
,@Geo
,@Culture
,@Other
,@IPAddress
,@NativeDeviceID);
IF(@OldUniqueID != ''-1'' AND @OldUniqueID != @UniqueID)
BEGIN
EXEC DeleteOldAndroidDeviceID @OldUniqueID, @UniqueID;
END
END
LBEXIT:
IF @TranCount = 0
COMMIT;
END TRY
BEGIN CATCH
DECLARE @Error INT, @Message VARCHAR(4000), @XState INT;
SELECT @Error = ERROR_NUMBER() ,@Message = ERROR_MESSAGE() ,@XState = XACT_STATE();
IF @XState = -1
ROLLBACK;
IF @XState = 1 AND @TranCount = 0
rollback
IF @XState = 1 AND @TranCount > 0
ROLLBACK TRANSACTION Insertorupdatedevicecatalog;
RAISERROR (''Insertorupdatedevicecatalog: %d: %s'', 16, 1, @error, @message) ;
END CATCH
END
已经讨论过
您可以在TSQL中使用sp_getapplock实现它
但是您需要一个包装器storedproc或批处理。检查以下示例,它将帮助您设计包装器sp/batch语句
示例代码片段
Create table MyTable
(
RowId int identity(1,1),
HitStartedAt datetime,
HitTimestamp datetime,
UserName varchar(100)
)
Go
Create proc LegacyProc (@user varchar(100), @CalledTime datetime)
as
Begin
Insert Into MyTable
Values(@CalledTime, getdate(), @user);
--To wait for 10 sec : not required for your procedures, producing the latency to check the concurrent users action
WAITFOR DELAY '000:00:10'
End
Go
Create Proc MyProc
(
@user varchar(100)
)
as
Begin
Declare @PorcName as NVarchar(1000), @CalledTime datetime
Begin Tran
--To get the Current SP Name, it should be unique for each SP / each batch
SET @PorcName = object_name(@@ProcID)
SET @CalledTime = Getdate()
--Lock the Current Proc
Exec sp_getapplock @Resource = @PorcName, @LockMode = 'Exclusive'
--Execute Your Legacy Procedures
Exec LegacyProc @user, @CalledTime
--Release the lock
Exec sp_releaseapplock @Resource = @PorcName
Commit Tran
End
您正在DeviceCatalog表上执行两个单独的更新,其中[UniqueID]=@UniqueID在同一事务中 我打赌您的锁定/请求超时问题发生在以下情况: 如果(@OldGeo为NULL或@OldAddress为NULL或@OldCity为NULL或@OldCountry为NULL或ISNULL(@Geo.STDistance(@OldGeo)/1000,0)>50)为真 尝试这样的方法来代替这两个更新 显然,先在dev中进行测试 在else子句中,如果when为false,则希望它插入一些内容。在这里,我只是插入当前的更新前字段内容
UPDATE DeviceCatalog
SET [OS] = @OS
,[Location] = @Geo
,[Culture] = @Culture
,[Other] = @Other
,[IPAddress] = @IPAddress
,[Lastmodifieddate] =
case when (
@OldGeo is NULL
OR
@OldAddress is NULL
OR
@OldCity is NULL
OR
@OldCountry is NULL
OR
ISNULL(@Geo.STDistance(@OldGeo) / 1000,0) > 50
) then Getdate()
else [Lastmodifieddate]
end
WHERE [UniqueID] = @UniqueID
超时是由于在同一事务中对同一表进行了两次更新。你可以通过案例陈述来避免它。也可以用合并替换整个IF-ELSE
MERGE INTO DeviceCatalog DC
USING (SELECT @UniqueID AS UniqueID) T ON (DC.UniqueID = T.UniqueID)
WHEN MATCHED THEN
UPDATE SET [OS] = @OS
,[Location] = @Geo
,[Culture] = @Culture
,[Other] = @Other
,[IPAddress] = @IPAddress
,[Lastmodifieddate] = (CASE
WHEN (LastUpdatedLocationFromJob IS NULL OR [Address] IS NULL OR [City] IS NULL OR [Country] IS NULL OR ISNULL(@Geo.STDistance(LastUpdatedLocationFromJob) / 1000,0) > 50)
THEN Getdate()
ELSE [Lastmodifieddate]
END)
WHEN NOT MATCHED THEN
INSERT INTO DeviceCatalog
([OS]
,[UniqueID]
,[Location]
,[Culture]
,[Other]
,[IPAddress]
,[NativeDeviceID])
VALUES (@OS
,@UniqueID
,@Geo
,@Culture
,@Other
,@IPAddress
,@NativeDeviceID)
WHEN NOT MATCHED BY SOURCE AND @OldUniqueID != ''-1'' AND @OldUniqueID != @UniqueID THEN
DELETE;
请尝试并检查这是否是您所期望的。您能否给出一个具体的示例,说明如果用户确实开始第二次执行,将会出现的实际问题?通常情况下,编写并行运行多次的代码应该是完全安全的。@Damien_不信者,我有一些select语句在insert/update操作之前获取变量中的表值。我想确保在这些select语句之后,只有同一SP中的insert/update操作才能运行,否则我的变量可能有错误的值,因为当时可能是同一SP在另一个请求中运行到完成。请查看事务隔离级别和共享锁usage@Damien_The_Unbeliever,我已经更新了问题hi,@user960567,很抱歉,但我不确定您的问题:您是在尝试改进响应时间以避免超时,还是在尝试评估超时事件(分析)?