簡體   English   中英

從臨時表鎖定-SQL 2008 R2

[英]Locking From Temp Table - SQL 2008 R2

我剛剛在我們的實時環境中實現了一個新數據庫,該數據庫由服務經紀人從我們兩個事務性數據庫中獲取的信息。 當消息進入新數據庫時,我們有一系列存儲過程,可為每個特定用戶操縱提要。

我還有另一組存儲過程,這些存儲過程按用戶而不是按車輛重新處理數據,我們的維護屏幕將使用這些存儲過程來確保我們可以更改用戶對數據的可見性。

下面的存儲過程一直處於鎖定狀態,我現在已經修改了該sp以首先更新臨時表,然后僅對主數據庫進行了一次更新,但是這對情況沒有幫助,因此我也進行了修改,因此可以小批量更新和如果失敗,請重試,直到成功。 這可以在我們的開發環境中100%起作用,但在實時運行中它會一直鎖定。 服務經紀人的吞吐量不足以記錄故障數量,因此,我相信我將自己鎖定在此范圍之內?

在故障點,我已包括---“此更新保持鎖定”。

是什么導致這種鎖定行為?

USE [Isight]

GO / **對象:StoredProcedure [dbo]。[UserVisibilityForVehicles]腳本日期:2014年7月18日14:43:04 ** / SET ANSI_NULLS ON進行QUOTED_IDENTIFIER ON進行

ALTER PROCEDURE [dbo]。[UserVisibilityForVehicles]-在此處添加存儲過程的參數@Username VARCHAR(50),RECOMPILE AS BEGIN開始–添加SET NOCOUNT ON以防止出現多余的結果集-干擾SELECT語句。 開啟NOCOUNT;

PRINT 'UserVisibilityForVehicles Started'

-- Now Start to check security for user.

IF EXISTS ( SELECT ID FROM dbo.SecurityTable WHERE userid = @Username AND Deleted = 0)
BEGIN


        CREATE TABLE #VehicleToUsers(ID BIGINT, NewRecord BIT DEFAULT(0))
        CREATE CLUSTERED INDEX IDX_VehicleToUsers ON #VehicleToUsers(ID)
        CREATE NonCLUSTERED INDEX IDX_NewRecord ON #VehicleToUsers(ID)

        INSERT INTO #VehicleToUsers
                ( ID )
        (
            SELECT Distinct Veh.[ID]
            FROM [iSight].[dbo].[Vehicle] Veh WITH (NOLOCK) 
            INNER JOIN SecurityTable WITH (NOLOCK) ON  Veh.[System] = SecurityTable.[System]
            WHERE SecurityType = 1  AND UserID = @Username AND SecurityTable.deleted = 0 
        )

        INSERT INTO #VehicleToUsers
                ( ID )
        (
            SELECT DISTINCT Veh.[ID]
            FROM [iSight].[dbo].[Vehicle] Veh WITH (NOLOCK) 
            INNER JOIN SecurityTable WITH (NOLOCK) ON Veh.[System] = SecurityTable.[System] AND Veh.CurrentSite = SecurityTable.[Site]
            WHERE SecurityType = 2 AND UserID = @Username AND SecurityTable.deleted = 0 
        )



                    BEGIN
                        PRINT 'UserVisibilityForVehicles: ' + @Username
                        INSERT INTO #VehicleToUsers
                                    ( ID )
                            (
                        SELECT  DISTINCT   Vehicle.ID
                        FROM         Manufacturer WITH (NOLOCK) INNER JOIN
                                              ManufacturerAgreementSubcustomer WITH (NOLOCK) ON Manufacturer.ID = ManufacturerAgreementSubcustomer.ManufacturerID INNER JOIN
                                              ManufacturerMake WITH (NOLOCK) ON Manufacturer.ID = ManufacturerMake.ManufacturerID INNER JOIN
                                              Vehicle WITH (NOLOCK) ON ManufacturerMake.Make = Vehicle.Make AND ManufacturerAgreementSubcustomer.Agreement = Vehicle.CurrentAgreement INNER JOIN
                                              SecurityTable WITH (NOLOCK) ON Manufacturer.ManufacturerGroupID = SecurityTable.ManufacturerGroupID AND Vehicle.System = SecurityTable.System
                        WHERE     (SecurityTable.SecurityType = 3)  AND (SecurityTable.UserID = @Username) AND ManufacturerMake.Deleted = 0 AND ManufacturerAgreementSubcustomer.Deleted = 0 AND SecurityTable.deleted = 0 
                            )

                            INSERT INTO #VehicleToUsers
                                    ( ID )
                            (
                        SELECT DISTINCT Vehicle.ID
                        FROM         Manufacturer WITH (NOLOCK) INNER JOIN
                                              ManufacturerAgreementSubcustomer WITH (NOLOCK) ON Manufacturer.ID = ManufacturerAgreementSubcustomer.ManufacturerID INNER JOIN
                                              ManufacturerMake WITH (NOLOCK) ON Manufacturer.ID = ManufacturerMake.ManufacturerID INNER JOIN
                                              Vehicle WITH (NOLOCK) ON ManufacturerMake.Make = Vehicle.Make AND ManufacturerAgreementSubcustomer.Agreement = Vehicle.CurrentAgreement INNER JOIN
                                              SecurityTable WITH (NOLOCK) ON Vehicle.System = SecurityTable.System AND Manufacturer.ID = SecurityTable.ManufacturerID
                        WHERE     (SecurityTable.SecurityType = 4) AND (SecurityTable.UserID = @Username) AND ManufacturerMake.Deleted = 0 AND ManufacturerAgreementSubcustomer.Deleted = 0 AND SecurityTable.deleted = 0 
                            )

                                INSERT INTO #VehicleToUsers
                                    ( ID )
                            (
                                SELECT DISTINCT Vehicle.ID
                                FROM         Manufacturer WITH (NOLOCK) INNER JOIN
                                                      ManufacturerAgreementSubcustomer WITH (NOLOCK) ON Manufacturer.ID = ManufacturerAgreementSubcustomer.ManufacturerID INNER JOIN
                                                      ManufacturerMake WITH (NOLOCK) ON Manufacturer.ID = ManufacturerMake.ManufacturerID INNER JOIN
                                                      Vehicle WITH (NOLOCK) ON ManufacturerMake.Make = Vehicle.Make AND ManufacturerAgreementSubcustomer.Agreement = Vehicle.CurrentAgreement INNER JOIN
                                                      SecurityTable WITH (NOLOCK) ON Vehicle.System = SecurityTable.System AND Manufacturer.ID = SecurityTable.ManufacturerID AND 
                                                      ManufacturerAgreementSubcustomer.ID = SecurityTable.ManufacturerAgreementSub INNER JOIN
                                                      ManufacturerUserAgreementSubcustomer WITH (NOLOCK) ON 
                                                      ManufacturerAgreementSubcustomer.ID = ManufacturerUserAgreementSubcustomer.ManufacturerAgreementSubcustomerID AND 
                                                      SecurityTable.ManufacturerID = ManufacturerUserAgreementSubcustomer.ManufacturerID AND 
                                                      SecurityTable.UserID = ManufacturerUserAgreementSubcustomer.UserName
                                WHERE     (SecurityTable.SecurityType = 5) AND (SecurityTable.UserID = @Username) AND (ManufacturerMake.Deleted = 0) AND 
                                                      (ManufacturerAgreementSubcustomer.Deleted = 0) AND (ManufacturerUserAgreementSubcustomer.Deleted = 0) AND SecurityTable.deleted = 0 


                            )


                                    INSERT INTO #VehicleToUsers
                                    ( ID )
                            (
                                SELECT DISTINCT Vehicle.ID
                                FROM         Manufacturer WITH (NOLOCK) INNER JOIN
                                                      ManufacturerAgreementSubcustomer WITH (NOLOCK) ON Manufacturer.ID = ManufacturerAgreementSubcustomer.ManufacturerID INNER JOIN
                                                      ManufacturerMake WITH (NOLOCK) ON Manufacturer.ID = ManufacturerMake.ManufacturerID INNER JOIN
                                                      Vehicle WITH (NOLOCK) ON ManufacturerMake.Make = Vehicle.Make AND ManufacturerAgreementSubcustomer.Agreement = Vehicle.CurrentAgreement AND 
                                                      ManufacturerAgreementSubcustomer.Subcustomer = Vehicle.CurrentSubCustomer INNER JOIN
                                                      SecurityTable WITH (NOLOCK) ON Vehicle.System = SecurityTable.System AND Manufacturer.ID = SecurityTable.ManufacturerID AND 
                                                      ManufacturerAgreementSubcustomer.ID = SecurityTable.ManufacturerAgreementSub INNER JOIN
                                                      ManufacturerUserAgreementSubcustomer WITH (NOLOCK) ON 
                                                      ManufacturerAgreementSubcustomer.ID = ManufacturerUserAgreementSubcustomer.ManufacturerAgreementSubcustomerID AND 
                                                      SecurityTable.UserID = ManufacturerUserAgreementSubcustomer.UserName AND 
                                                      SecurityTable.ManufacturerID = ManufacturerUserAgreementSubcustomer.ManufacturerID
                                WHERE     (SecurityTable.SecurityType = 6) AND (SecurityTable.UserID = @Username) AND (ManufacturerMake.Deleted = 0) AND 
                                                      (ManufacturerAgreementSubcustomer.Deleted = 0) AND (ManufacturerUserAgreementSubcustomer.Deleted = 0) AND SecurityTable.deleted = 0 
                            )


                    END

        CREATE TABLE #VehicleToUserCopy(ID BIGINT, vehicleTableID BIGINT, Deleted BIT DEFAULT(1), UpdatedAt DATETIME DEFAULT (GETDATE()), UpdatedBy VARCHAR(50) DEFAULT('UserVisibilityForVehicles-Update'), NextToUpdate BIT DEFAULT(0))

        CREATE CLUSTERED INDEX idx_ID ON #VehicleToUserCopy(ID)
        CREATE NONCLUSTERED INDEX idx_VehicleTableID ON #VehicleToUserCopy(vehicleTableID)
        CREATE NONCLUSTERED INDEX idx_NextToUpdate ON #VehicleToUserCopy(NextToUpdate)
        INSERT INTO #VehicleToUserCopy
                ( ID ,
                  vehicleTableID ,
                  Deleted
                )
        (
        SELECT ID, vehicleTableID, Deleted
        FROM dbo.VehicleToUser WITH (nolock)
        WHERE Username = @Username

        )


        PRINT 'Starting to do updates'
        --Not required as default set to 1
        ----UPDATE VehicleToUser
        ----SET DELETED = 1
        ----,UpdatedAt = GETDATE()
        ----,UpdatedBy = 'UserVisibilityForVehicles'
        ----FROM dbo.VehicleToUser WITH (NOLOCK)
        ----LEFT JOIN #VehicleToUsers AS UsersVehicles ON VehicleToUser.VehicleTableID = UsersVehicles.ID
        ----WHERE UserName = @Username AND UsersVehicles.ID IS null

        PRINT 'Starting to do updates - Set Deleted = 0'




        SET LOCK_TIMEOUT 1000 -- set to  second
        DECLARE @Tries tinyint


        UPDATE #VehicleToUserCopy
        SET Deleted = 0
        FROM #VehicleToUserCopy AS VehicleToUserCopy
        inner JOIN #VehicleToUsers AS UsersVehicles ON VehicleToUserCopy.VehicleTableID = UsersVehicles.ID




        INSERT INTO VehicleToUser(UserName, VehicleTableID, DELETED, UpdatedAt, UpdatedBy)
        (
            SELECT DISTINCT @Username, TempVehicle.ID, 0 , GETDATE(), 'UserVisibilityForVehicles-Insert'
            FROM #VehicleToUsers AS TempVehicle
            LEFT JOIN (
                        SELECT VehicleTableID
                        FROM #VehicleToUserCopy WITH (NOLOCK)
                      ) AS [VehicleToUser] ON TempVehicle.ID = [VehicleToUser].VehicleTableID
            WHERE [VehicleToUser].VehicleTableID IS null

        )

        DECLARE @ID bigint

        SELECT @ID = ID FROM #VehicleToUserCopy
        WHILE @@rowcount > 0 
            BEGIN

                    SET ROWCOUNT 1000
                    SELECT @Tries = 1
                    WHILE @Tries <= 3

                          BEGIN

                         BEGIN TRANSACTION

                         BEGIN TRY

                                UPDATE #VehicleToUserCopy SET NextToUpdate = 1


                                 ---'THIS UPDATE KEEPS LOCKING'
                                UPDATE dbo.VehicleToUser
                                SET Deleted = VehicleToUserCopy.Deleted
                                , UpdatedAt = GETDATE()
                                , UpdatedBy = VehicleToUserCopy.UpdatedBy
                                FROM VehicleToUser
                                inner JOIN #VehicleToUserCopy  AS VehicleToUserCopy ON VehicleToUser.ID = VehicleToUserCopy.ID
                                WHERE VehicleToUserCopy.NextToUpdate = 1            

                                PRINT 'WORKED'
                                DELETE FROM #VehicleToUserCopy WHERE NextToUpdate = 1   
                                COMMIT    

                          -- therefore we can leave our loop
                          BREAK

                         END TRY

                         BEGIN CATCH

                                ROLLBACK --always rollback 


                            PRINT 'Rolled Back '
                          -- Now check for Blocking errors 1222 or Deadlocks 1205 and if its a deadlock wait for a while to see if that helps
                             SELECT ERROR_MESSAGE()
                              IF ERROR_NUMBER() = 1205 OR ERROR_NUMBER() = 1222

                                BEGIN

                                     -- if its a deadlock wait 2 seconds then try again
                                   IF ERROR_NUMBER() = 1205
                                     BEGIN  -- wait 2 seconds to see if that helps the deadlock

                                            WAITFOR DELAY '00:00:02'
                                     END   

                                   -- no need to wait for anything for BLOCKING ERRORS as our LOCK_TIMEOUT is going to wait for half a second anyway
                                   -- and if it hasn't finished by then (500ms x 3 attempts = 1.5 seconds) there is no point waiting any longer

                                END      


                                 SELECT @Tries = @Tries + 1  -- increment and try again for 3 goes

                          -- we carry on until we reach our limit i.e 3 attempts
                          CONTINUE    

                           END CATCH

                          END



                SELECT @ID = ID FROM #VehicleToUserCopy 
            End


        SET ROWCOUNT 0


        DROP TABLE #VehicleToUsers


END
ELSE

BEGIN
        DELETE FROM dbo.VehicleToUser WHERE username = @Username
        DELETE FROM dbo.VehicleToUser_UserCurrentImageCount WHERE username = @Username
        DELETE FROM dbo.VehicleToUser_UsersCurrentVehicles WHERE username = @Username

End

嘗試稍微更改您的更新。 使用此類更新並更新基表時,我看到了一些不一致的結果。 您應該改為更新別名。

UPDATE v
SET Deleted = VCopy.Deleted
, UpdatedAt = GETDATE()
, UpdatedBy = VCopy.UpdatedBy
FROM VehicleToUser v
inner JOIN #VehicleToUserCopy  AS VCopy ON v.ID = VCopy.ID
WHERE VCopy.NextToUpdate = 1            

暫無
暫無

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

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