在數據庫並發情況下避免插入重復數據的一個解決方法


目前公司的項目中碰到一個情況:需要向一個數據表table1中插入記錄,該表的結構類似於下面的定義:

列名  類型 是否允許為空
Id int no
Area string no
AreaIndex int no
Name string no

其中Name的值由Area和AreaIndex拼接而成,形式類似於“Area+AreaIndex”。對於相同的Area,AreaIndex從1開始計數,所以對於Area分別為“AA”,“BB”,“CC”的情況,Name的值類似下面這樣:

AA001 AA002 BB001 AA003 BB002 CC001這種形式。

當插入新值的時候,需要判斷數據表中該Area的最大AreaIndex,在此基礎上加1做為新行的AreaIndex,同時拼接Name到數據庫中。在數據庫並發的情況下,會出現大量相同記錄的情況。

目前想到的一個比較好的解決方法就是:

1,創建一個新表Table2來存儲Area的最大AreaIndex,當插入新記錄時,從新表中獲取最大AreaIndex,加一作為新記錄的AreaIndex,同時更新新表的最大AreaIndex。

2,創建一個新的存儲過程來添加記錄到表中。在該存儲過程中,先查詢Table2並鎖定該表。獲取插入記錄對應Area的最大AreaIndex並更新Table2中的記錄后,插入記錄到Table1中。存儲過程的代碼類似下面這樣:

BEGIN
      BEGIN TRAN
      DECLARE @MaxAreaIndex int      
      

      --查詢並鎖定Table2
      SELECT @MaxAreaIndex = AreaIndex
      FROM    Table2 WITH (TABLOCKX)
      WHERE  Area= @Area
      

      --獲取到最大的AreaIndex后,更新Table2
      IF @MaxAreaIndex IS NULL
          BEGIN

     --如果Table2中沒有記錄,則新增一條記錄
             SET @MaxAreaIndex = 1
             INSERT INTO [Table2]
                   ([MaxAreaIndex] ,[Area])
             VALUES
                   (@MaxAreaIndex, @Area)
          END
      ELSE

    BEGIN    

               SET @MaxAreaIndex = @MaxAreaIndex  + 1
               UPDATE Table2
               SET       MaxAreaIndex = @MaxAreaIndex
               WHERE  Area = @Area

    END
    
     INSERT INTO Table1
           ([Name] ,[Area] ,[AreaIndex])
     VALUES
           (@Area+ RTRIM(LTRIM(STR(@MaxAreaIndex))) ,@Area ,@MaxAreaIndex)
    
    COMMIT TRAN

 

關鍵的代碼在:

      SELECT @MaxAreaIndex = AreaIndex
      FROM    Table2 WITH (TABLOCKX)
      WHERE  Area= @Area

當在存儲過程中對表Table2進行加鎖后,其他對該存儲過程的調用就必須等待前一次執行完成並釋放對表的鎖定后才能繼續執行。

在Area不是很多的情況下,效率沒有大的影響。

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM