簡體   English   中英

不同連接上的SQL Server存儲過程

[英]SQL Server Stored Procedure on Diferent Connection

我有一個存儲過程,可以從表中獲得唯一的引用。 您傳入一個代碼,例如為itemref輸入“ I”或為tranref輸入“ T”,那么還有其他代碼,然后存儲過程將查找表,增加數字並返回該數字(這樣其他人可以擁有下一個數字等等。)。

但是,在對象級別(vb.net),我想獲取不同連接上的引用,該引用永遠不會通過在事務中間訪問該表來鎖定該表。 這一直很好,直到測試時我碰到一些代碼,在該代碼中另一個存儲過程(在發布發票的事務中)也稱為get_ref存儲過程,這很好,直到對象嘗試再次獲取它然后鎖定系統為止。

是否有一種方法可以使存儲過程僅在不同的連接/事務級別上調用另一個存儲過程?

這是get_ref存儲過程:

CREATE PROCEDURE get_ref 
    (@Ref NUMERIC(28,0) OUTPUT, 
     @RefType VARCHAR(8), 
     @AddVal NUMERIC(28,0) = NULL)
AS
    SET NOCOUNT ON

    DECLARE @VALINC int

    IF @Addval IS NULL
        SET @VALINC = 1
    ELSE
        IF @Addval > 0
            SET @VALINC = @Addval
        ELSE
            SET @VALINC = 1

    IF UPPER(@RefType) = 'HM'
    BEGIN
        BEGIN TRANSACTION
            UPDATE HMREFS 
            SET REF = REF + @valinc

            IF (@@ERROR <> 0)
                GOTO ERRLAB

            SELECT @ref = REF 
            FROM HMREFS

            IF (@@ERROR <> 0)
                GOTO ERRLAB

            COMMIT TRANSACTION
    END
    ELSE
        IF UPPER(@RefType) = 'T'
        BEGIN
            BEGIN TRANSACTION
                UPDATE sysgen 
                SET TRANREF = TRANREF + @valinc

                IF (@@ERROR <> 0)
                    GOTO ERRLAB

                SELECT @ref = TRANREF FROM sysgen

                IF (@@ERROR <> 0)
                    GOTO ERRLAB

                COMMIT TRANSACTION
    END
    ELSE
        IF UPPER(@RefType) = 'I'
        BEGIN
            BEGIN TRANSACTION
                UPDATE sysirgen 
                SET ITEMREF = ITEMREF + @valinc

                IF (@@ERROR <> 0)
                    GOTO ERRLAB

                SELECT @ref = ITEMREF FROM sysirgen

                IF (@@ERROR <> 0)
                    GOTO ERRLAB

                COMMIT TRANSACTION
        END
    RETURN 0

ERRLAB:
    ROLLBACK TRANSACTION
    RAISERROR ('Error Getting Reference', 16, 1)
    RETURN 1
GO

我有與數據庫有兩個連接的程序。 用於獲取引用等的Connection1。這將永遠不會使用Begin事務,因為我不想阻止任何其他用戶訪問相同的表。 用於執行工作的Connection2。

我的程序將獲得Connection1上發票的參考,然后在Connection2上開始交易並完成將所述發票存放在SP1中的工作。 但是,由於涉及庫存(在某些情況下可能不涉及),因此SP1必須調用SP get_ref,以便它可以插入庫存移動線。 然后,這將鎖定存儲過程get_ref訪問的表,直到提交Connection2。 但是,發票已過帳,SP1返回程序。 在我的程序提交Connection2之前,它必須分派貨物(如果有),並留在交易中。 然后,它在Connection1上調用引用,該引用已鎖定,因為Connection2上的SP1已訪問了它想要的表。 然后程序崩潰。

當前及其過去的工作方式是所有工作都在同一個連接上,因此沒有死鎖問題,除非我們涉及到運行時間較長的流程而其他人也這樣做。 在這種情況下,我們將遇到其他人登錄時出現的死鎖問題。這不是我們經常遇到的問題,但是我們希望對此進行整理。 因此,嘗試訪問其他事務上的get_ref表。

看到一些代碼調用此過程會很有幫助,但是這里有多個事務在進行。 我建議對此進行重做以利用TRY / CATCH。 它使代碼易於遵循。 您很有可能掛起了一個事務,這就是導致您之前鎖定的原因。

這樣的事情。

CREATE PROCEDURE get_ref 
(
    @Ref numeric(28,0) OUTPUT
    , @RefType VARCHAR(8)
    , @AddVal numeric(28,0) = NULL
) AS

    SET NOCOUNT ON;

DECLARE @VALINC int

--rewritten as a case expression below  
--IF @Addval IS NULL
--    SET @VALINC = 1
--ELSE
--    IF @Addval > 0
--        SET @VALINC = @Addval
--    ELSE
--        SET @VALINC = 1

select @VALINC = case when isnull(@AddVal, 0) = 0 OR @AddVal < 0 then 1 else @AddVal end

BEGIN TRY
    BEGIN TRANSACTION

    IF UPPER(@RefType) = 'HM'
        BEGIN
            UPDATE HMREFS SET REF = REF + @valinc
            SELECT @ref = REF FROM HMREFS
        END
    ELSE
        IF UPPER(@RefType) = 'T'
        BEGIN
            UPDATE sysgen SET TRANREF = TRANREF + @valinc
            SELECT @ref = TRANREF FROM sysgen
        END
    ELSE
        IF UPPER(@RefType) = 'I'
        BEGIN
            UPDATE sysirgen SET ITEMREF = ITEMREF + @valinc
            SELECT @ref = ITEMREF FROM sysirgen
        END
    COMMIT TRANSACTION
    --there is no point in returning 0, that is the default return value when a procedure completes without error
END TRY

BEGIN CATCH
    ROLLBACK TRANSACTION
    RAISERROR ('Error Getting Reference', 16, 1)
    RETURN 1
END CATCH

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM