我无法找到任何解释为什么在调用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] ) )
有人可以解释为什么我会看到这个问题,这意味着什么,更重要的是我如何解决它?
感谢
答案 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