Sql server MS SQL时态表更新失败

Sql server MS SQL时态表更新失败,sql-server,tsql,azure-sql-database,sql-server-2016,Sql Server,Tsql,Azure Sql Database,Sql Server 2016,我找不到任何东西来解释为什么在调用执行插入或更新的SP时,该SP取决于我得到的时态表上是否已经存在记录 在系统版本表上修改数据失败 “MYDB.dbo.TemporalExample”,因为事务时间早于 受影响记录的时段开始时间 那是什么意思?这似乎只是在某些时候发生的,我想知道这是否是因为我运行多线程代码和azure sql不喜欢同一个表的相互连接,而它是临时的?我正在浏览实体框架的最新版本,但我怀疑这是问题所在 我的sp就是这个 create PROCEDURE mysp @ID

我找不到任何东西来解释为什么在调用执行插入或更新的SP时,该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] ) ) 有人能解释一下我为什么会看到这个问题,它意味着什么,更重要的是我如何解决它吗


谢谢

所以我解决了这个问题……似乎时态表不能很好地处理线程逻辑。我怀疑是因为我并行地对表进行多个并发更新;链接的历史记录表更新滞后,时间链接导致故障。使我的代码成为单线程解决了这个问题。这似乎很奇怪,临时表将受到什么似乎几乎是一个种族条件?我知道这不是我的代码,因为相同的代码适用于其他表。因此,我想我必须坚持使用单线程逻辑,直到MS修复它。这是一种黑客的解决方法,在大多数情况下并不理想。但是,如果您在处理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  

你为什么要更新临时表我不知道为什么我不更新它?这毕竟是一个正常的表,我没有更新历史表,这是根据MS docs,当你需要更新表中的数据时,你仍然可以使用正常的更新方法。哦,好的,我想这是历史表。你不是在使用分区吗?我为我的临时表添加了创建脚本,不,我没有为更新使用分区,因为我不想将更新限制在设定的时间段内,根据MS文档,我必须这样做?您通过实体框架过程调用显式事务?我使用azure实体框架调用,该框架支持重试策略并支持异步方法。您实际上是指从多线程迁移到单线程,如按顺序插入而不是并发插入?还是说从异步/等待模式迁移到常规的同步方法?我意识到async/await模式与线程有关,但我只是想澄清一下,让代码成为单线程的确切含义。我从并行async/await任务更改为spyer问题的同步方法调用,重点是支持azure实体框架附带的异步方法。我总是可以使用单线程逻辑,但理想情况下,您可以想象时态表可以使用异步逻辑。话虽如此,我注意到您不能在临时表上调用truncate,我认为这很奇怪,因此它们可能不支持线程等其他功能。但是感谢您的建议: