繁体   English   中英

SQL Server 2016-创建不存在的记录时存储过程锁定

[英]SQL Server 2016 - stored procedure lock when creating not existing records

我的数据库中有以下表格:

------------------------------------------
| EventDefinitions                       |
------------------------------------------
| EventDefinitionId:    uniqueidentifier |
| Code:                 varchar(63)      |
| EventSystem:          int              |
------------------------------------------

------------------------------------------
| Event                                  |
------------------------------------------
| EventId:              uniqueidentifier |
| EventDateTime:        datetime2        |
| EventDefinitionId:    uniqueidentifier |
------------------------------------------

EventDefinitions(1)<-事件(n)
EventDefinition对EventSystem和Code具有唯一的约束。

我正在研究一个存储过程,该存储过程应基于指定的Code和EventSystem创建一个Event记录并将其映射到正确的EventDefinition记录。
如果不存在匹配的EventDefinition,则该过程应创建一个新的EventDefinition。
该过程将由多个应用程序同时执行。

我的目标:

  • 该过程必须是并行可执行的。
    使用尽可能少的锁,以便可以同时写入多个事件记录。
  • 当EventDefinition不存在时,应仅由一个进程创建。
    该过程应该创建某种锁,以确保具有指定Code和EventSystem的EventDefinition记录仅创建一次(否则,数据库将抛出唯一的约束冲突异常)。 其他进程应将事件记录映射到新创建的EventDefinition记录。

到目前为止,这是我尝试过的:

CREATE PROCEDURE dbo.procWriteEvent @eventCode varchar(63), @eventSystem int
AS
    DECLARE @eventDefinitionId uniqueidentifier
    DECLARE @insertedEventDefinition table(EventDefinitionId uniqueidentifier)
    DECLARE @currentLevel varchar(255)
    BEGIN TRANSACTION
        -- Try read event definition
        SET @eventDefinitionId = (SELECT TOP 1 EventDefinitionId FROM EventDefinitions WHERE EventSystem = @eventSystem AND Code = @eventCode )

        -- Create event definition if not exists
        IF @eventDefinitionId IS NULL
            BEGIN
                BEGIN TRANSACTION
                    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
                    -- Check if event definition was created by an other process
                    SET @eventDefinitionId = (SELECT TOP 1 EventDefinitionId FROM EventDefinitions WHERE EventSystem = @eventSystem AND Code = @eventCode )

                    -- Create event definition
                    IF @eventDefinitionId IS NULL
                        BEGIN
                            INSERT INTO EventDefinitions (Code, EventSystem, Severity)
                                OUTPUT Inserted.EventDefinitionId INTO @insertedEventDefinition
                                VALUES (@eventCode, @eventSystem, 0)

                            SET @eventDefinitionId = (SELECT TOP 1 EventDefinitionId FROM @insertedEventDefinition)
                        END
                COMMIT TRANSACTION
                SET TRANSACTION ISOLATION LEVEL READ COMMITTED
            END

        INSERT INTO Events (EventDefinitionId, EventDateTime)
            VALUES (@eventDefinitionId, GETDATE())

    COMMIT TRANSACTION

问题是,我的当前SQL代码在并行执行过程时会产生死锁。

您的代码过于复杂。 SQL Server会执行最多的检查并自行阻止。 只需尝试/捕获插入,如果由于违反UNIQUE约束而失败,请重新读取EventDefinitions。 的种类

CREATE PROCEDURE dbo.procWriteEvent @eventCode varchar(63), @eventSystem int
AS
    DECLARE @eventDefinitionId uniqueidentifier
    DECLARE @insertedEventDefinition table(EventDefinitionId uniqueidentifier)
    DECLARE @currentLevel varchar(255)
    -- Try read event definition
    SET @eventDefinitionId = (SELECT TOP 1 EventDefinitionId FROM EventDefinitions WHERE EventSystem = @eventSystem AND Code = @eventCode )
    -- Create event definition if not exists
    IF @eventDefinitionId IS NULL
    BEGIN TRY
        INSERT INTO EventDefinitions (Code, EventSystem, Severity)
        OUTPUT Inserted.EventDefinitionId INTO @insertedEventDefinition
        VALUES (@eventCode, @eventSystem, 0);
        SET @eventDefinitionId = (SELECT TOP 1 EventDefinitionId FROM @insertedEventDefinition)
    END TRY
    BEGIN CATCH
        SET @eventDefinitionId = (SELECT TOP 1 EventDefinitionId FROM EventDefinitions WHERE EventSystem = @eventSystem AND Code = @eventCode )
    END CATCH
    -- proceed with @eventDefinitionId value

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM