解決多線程調用sql存儲過程問題


  • 場景:

我們程序現在改成多線程了,我現在需要把臨時表中的數據給插入到TABLE_M中,但這時候可能其他的線程也在插入,我就不能用之前我們的方案了(select max(oid) from Tuning.TABLE_M。。。,之后去維護主子表關系,改掉TABLE_M的OID的自增屬性,插入,之后再添加上自增屬性。。。。。。)

我現在是想這樣操作:

1,)先插入把臨時數據插入到TABLE_M(OID是自增的)中(Insert Into ….select …),我之后獲取 select Scope_Identity() as @MaxTABLE_MOID,之后根據這個@MaxTABLE_MOID去修改臨時表中的TABLE_MOID.

1.1,)(1,)這種方案會不會出現以下問題:

A線程, 1-10 共10條記錄,

B 線程,1-10 共10條記錄 

A線程插入的時候,

B線程也在再插入 

A線程 與 B線程是交互的插入,A線程插入一條,B線程插入一條 

運行起來像這樣:

比如 此時TABLE_M的OID為 100 

A線程插入第一條 TABLE_M的OID變為 101

B線程插入第一條 TABLE_M的OID變為 102 

當我A線程插入完的時候,我A線程最后一條記錄插入的OID為 120 

這時候我的Temp 要到這個120 去修改字表關系 

TABLE_M(OID=120) 是A 插入的沒問題 

TABLE_M(OID=119)是B插入的,這時卻關聯到了A線程對應的臨時表的第9條記錄 

悲哀!!!

1.2,)我們是不是要在插入的時候使用With(lock)

2,)我還有一種想法,就是先插入完成后,根據條件查詢出該批數據插入TABLE_M的生成的OID,之后這些OID去和temp匹配(按照順序匹配,因為插入temp肯定是有序的插入),之后修改temp中的TABLE_MOID,這樣就可以把子數據插入到TABLE_M_LteCell,TABLE_M_GsmCell,TABLE_M_TdsCell中。

  • DBA提供解決方案

我們可以單獨做一個表來進行OID自增的維護,可以暫時稱為MAX_OID表。最簡單的方式是里面僅僅記錄:當前最大的OID。 

    這樣我們在做多線程操作的時候遵循以下步驟 

    1. 取得MAX_OID表中的值,這樣就可以獲得自增的起始序列號‍

    2. 獲得此次插入時候的臨時表的最大行數。不要使用select count(1) from table,使用如下語句,可以獲得最大的性能。

        直接獲取表行數sql語句:

        select sum(row_count)

        from sys.dm_db_partition_stats

        where index_id<1 and object_id=object_id('表名')

    3. 使用max_oid+臨時表的表行數,可以得到將臨時表插入到主表之后,主表未來最大的MAXOID號

    4. 更新MAX_OID表。將表內數據改為:‍max_oid+臨時表的表行數‍ 

    特別注意:為了保證事務一致性,上述步驟需要在一個事務中完成,需要以下語句 

    SET XACT_ABORT ON

    begin tran

         執行的sql語句(即上面1-4的邏輯操作)

    commit 

    以上四個步驟雖然文字上比較啰嗦,但是實際操作會非常快。使用的全是系統表來讀取,肯定是在毫秒級別,不會影響性能。

    這樣,每個線程讀取的都是MAX_OID表中的值,就不會產生沖突了。‍ 

    如下面的例子:

    目前MAX_OID 最大值為100.‍

    線程一的臨時表為30行

    線程二的臨時表為40行    

    線程一:

    1.讀取MAX_OID 表。得到100‍

    2.獲得臨時表行數:30

    3.得到預測的maxoid為100+30=130

    4.將MAX_OID 更改為130.‍ 

    線程二:

    1.讀取MAX_OID 表。得到130

    2.獲得臨時表行數:40

    3.得到預測的maxoid為130+40=170

    4.將MAX_OID 更改為170.

    注意:線程二得到的MAX_OID 一定是130,而不是100.因為線程一已經更新了這個值。且更新的過程中加鎖。線程二是讀取不到100這個數值的。‍ 

 這樣就可以避免沖突了。


免責聲明!

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



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