Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.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 有时仅从一个SP获取请求超时?_Sql_Tsql_Sql Server 2008 R2 - Fatal编程技术网

Sql 有时仅从一个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

我有很多存储过程。但有时我只收到此SP的请求超时

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,很抱歉,但我不确定您的问题:您是在尝试改进响应时间以避免超时,还是在尝试评估超时事件(分析)?