当前位置: 首页 > 知识库问答 >
问题:

MS SQL 临时表更新失败

刘选
2023-03-14

我找不到任何东西来解释为什么当调用一个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个答案

严正初
2023-03-14

这是一种黑客式的解决方法,在大多数情况下并不理想,但是,如果要在处理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  
魏烨熠
2023-03-14

所以我解决了这个问题…似乎时态表不能很好地处理线程逻辑。我怀疑这是因为我并行地对表进行多个并发更新;链接的历史记录表的更新滞后到时间链接导致故障的程度。使我的代码成为单线程解决了这个问题。似乎很奇怪,时态表会受到几乎是一种竞争条件的约束?我知道这不是我的代码,因为相同的代码适用于其他表。因此,我想我将不得不坚持单线程逻辑,直到MS修复它

 类似资料:
  • 我很困惑,因为当我在SQLite上运行这个查询时。 在MacOS Mojave SQLITE上,我在“FROM”上得到一个语法错误。没有更多的细节。 这对Postgres有效。 我是否以错误的方式阅读了 SQLite 文档?https://sqlite.org/lang_update.html 以下是查询: 设置查询:

  • 我试图用以下方式使用RODBC更新全局临时表: Select查询执行良好,但sqlUpdate失败,出现错误消息:“odbcTableExists(channel,tablename)中的错误:'##temptable':channel上找不到表”

  • 主要内容:示例,删除临时表关系型数据库支持临时表,这是一项很棒的功能。临时表的概念由 SQL Server 引入,用来存储和处理中间结果。 临时表在会话期间创建,会话结束后自动被删除。临时表可以和普通表一样执行各种操作,比如 SELECT、UPDATE、INSERT、JOIN 等。 MySQL 3.23 及其更高版本才支持临时表,如果您使用的 MySQL 版本低于 3.23,则不能使用临时表,但可以使用堆表(Heap Ta

  • 每次我尝试打开玩家设置,它将只显示空白。下面的错误将显示在控制台中。 我尝试过以下链接:https://answers.unity.com/questions/1320634/unable-to-list-target-platforms-when-i-try-to-build.html,但仍然没有工作。 CommandInvokationFailure:无法更新Android SDK包列表。/a

  • 我试图使用JDBC更新一个MSSQL实例,使用一个预先准备好的语句,在给定列名、要更新的值和更新的值时,我创建了一个方法来更新表中的任何记录。 第一个print语句打印出正确的值,这样我就知道输入是正确的,第二个print语句让我知道1行受影响,这是正确的。 如果我在Management Studio中运行脚本,脚本会运行良好并更新表,但如果我从java项目中运行脚本,则不会更新任何内容,也不会生