MS SQL时态表更新失败

时间:2016-11-18 08:37:29

标签: sql-server tsql azure-sql-database sql-server-2016

我无法找到任何解释为什么在调用SP时执行插入或更新的原因,具体取决于我是否已在时态表上存在记录

  

系统版本表上的数据修改失败   ' MYDB.dbo.TemporalExample'因为交易时间早于   受影响记录的期间开始时间。

这意味着什么剂量?它似乎只是在某些时候发生,我想知道它是否因为我运行多线程代码和azure sql只是不喜欢在同一个表的临时连接时相互连接?我通过实体框架(最新版本),但我怀疑这是问题

我的sp就是这个


create PROCEDURE mysp 
    @ID bigint,
    @a FLOAT,
    @b NVARCHAR(10),
    @c  DECIMAL(19, 4)
AS
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED    

    SET NOCOUNT ON    

    BEGIN TRY

        IF EXISTS ( SELECT TOP 1 
                        Id 
                    FROM 
                        my_Temporal_Table WITH (NOLOCK) 
                    WHERE 
                        id = @ID 
                        AND a = @a
                        AND b = @b)
            BEGIN

                UPDATE 
                    my_Temporal_Table
                SET
                    Id = @ID,
                    a = @a,
                    b = @b
                    c = @c
                    DateModified =  GETUTCDATE()
                WHERE 
                    Id = @Id

            END
        ELSE    
            BEGIN

                INSERT INTO 
                    my_Temporal_Table
                        (Id, a, b, c, DateModified)
                VALUES 
                        (@ID, @a, @b, @c , GETUTCDATE())        
            END

    END TRY
    BEGIN CATCH
        DECLARE @ErrorMessage   NVARCHAR(4000),
                @ErrorSeverity  INT,
                @ErrorState     INT

        SELECT 
                @ErrorMessage = ERROR_MESSAGE(),        
                @ErrorSeverity = ERROR_SEVERITY(),
                @ErrorState = ERROR_STATE()

        -- Use RAISERROR inside the CATCH block to return error
        -- information about the original error that caused
        -- execution to jump to the CATCH block.
        RAISERROR (@ErrorMessage, -- Message text.
                   @ErrorSeverity, -- Severity.
                   @ErrorState -- State.
                   )

    END CATCH

更新 我的临时表创建脚本:


    CREATE TABLE [Temporal](
    [TemporalId] [bigint] IDENTITY(1,1) NOT NULL,
    [Payment] [decimal](19, 4) NOT NULL,
    [DateModified] [datetime2](7) NOT NULL,
    [SysStartTime] [datetime2](7) GENERATED ALWAYS AS ROW START NOT NULL,
    [SysEndTime] [datetime2](7) GENERATED ALWAYS AS ROW END NOT NULL,
    CONSTRAINT [TemporalId] PRIMARY KEY CLUSTERED ([TemporalId] ASC)
        WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON),
    PERIOD FOR SYSTEM_TIME ([SysStartTime], [SysEndTime])
    )WITH(
    SYSTEM_VERSIONING = ON ( HISTORY_TABLE = [Car2].[TemporalHistory] )
    )

有人可以解释为什么我会看到这个问题,这意味着什么,更重要的是我如何解决它?

感谢

2 个答案:

答案 0 :(得分:0)

所以我解决了......似乎时态表不适合线程逻辑。我怀疑是因为我并行地对表进行多个并发更新;链接的历史表在其更新中滞后,以至于时间链接导致失败。使我的代码单线程修复了这个问题。奇怪的是,时间表会受到似乎几乎是竞争条件的影响?我知道它不是我的代码,因为相同的代码适用于其他表。所以我想我必须坚持单线程逻辑,直到MS修复它

答案 1 :(得分:0)

这是一种hackish解决方法,在大多数情况下并不理想,但是,如果您想在处理sql server时序列化对关键部分的访问,那么您可以使用内置锁定机制通过以下方式授予对该关键部分的访问权限SP_GETAPPLOCK但是,根据具体情况,您可能正在将瓶颈移到另一个位置。

CREATE PROC MyCriticalWork(@MyParam INT)      
AS
    DECLARE @LockRequestResult INT=0    
    DECLARE @MyTimeoutMiliseconds INT=5000--Wait only five seconds max then timeouit

    BEGIN TRAN

    EXEC @LockRequestResult=SP_GETAPPLOCK 'MyCriticalWork','Exclusive','Transaction',@MyTimeoutMiliseconds
    IF(@LockRequestResult>=0)BEGIN

            /*
            DO YOUR CRITICAL READS AND WRITES HERE
            */

        COMMIT TRAN--Releases the lock
    END ELSE
        ROLLBACK TRAN--Releases the lock