2016-09-16 81 views
0

我必須在表格Transaction中爲每行生成number_order(順序爲:1,2,3 ...)。我的解決方案是在插入表事務之前創建一個觸發器。觸發器的任務是統計表的總行數(從Transaction中選擇count(1)到v_count) - >然後設置:new.num_order = v_count + 1.在觸發器中處理多線程

該解決方案几乎可以運行正常,但是當系統有很多許多線程插入到表中,觸發器通過多線程執行,並返回相同的順序(原因是選擇命令在插入之前稱爲同一時間&)。 你能爲我提供一個替代解決方案嗎?先謝謝你。 P/s:我正在使用oracle 12c數據庫。而且我不能使用順序,因爲順序實際上基於表中的其他一些列(例如:Room_id)。因此,完整的選擇命令是:select count(1)to v_count from room_id =:new.room_id)

回答

1

通常,這是一種糟糕的方法,會導致顯着的性能,縮放和支持問題。我會重新考慮這個設計。

如果你想這樣做,你需要強制你的事務序列化。您可以使用主鍵爲room_idroom_count值的單獨表格,或者可以將該列添加到room。您需要通過select for update鎖定room_id的行。然後,您將更新room_count並將其用於您的insert。鎖定將在您的事務提交時釋放。

但是,如果您這樣做,則涉及相同room_id的每個其他交易都將被阻止。如果您的交易時間相對較短,假設您沒有太多的用戶與同一個房間一起工作,那麼這可能並不可怕。隨着用戶數量和交易時間的增加,問題變得更加困難。如果交易涉及多個房間,則您需要每筆交易以相同的順序處理它們(例如,以room_id爲例),以避免潛在的死鎖。如果你打算做的事情不僅僅是這張桌子,事情會變得更加複雜。

我寧願使用一個序列,然後在查詢中生成順序值。例如

SELECT room_id, 
     rank() over (partition by room_id order by sequence_column) your_num_order 
    FROM your_table 

或者你可以使用sequence_column的初始插件,並有後臺作業定期(每天是常見的),並在批處理分配num_order交易完成後。在before insert觸發

Create or replace function inc_room_cnt(p_room_id NUMBER) return number as 
PRAGMA autonomous_transaction; 
    v_cnt NUMBER; 
begin 
    update room_count set cnt = cnt +1 where room_id = p_room_id returning cnt into v_cnt; 

    -- insert new room if not yet exists 
    if SQL%ROWCOUNT = 0 then 
    v_cnt := 1; 
    insert into room_count values (p_room_id, v_cnt); 
    end if; 

    commit; 
    return v_cnt; 
end; 
/

可以撥打inc_room_cnt設置:

+0

非常感謝。但這個解決方案對我來說似乎很複雜 – Khoa

+0

@Khoa,解決方案非常複雜,因爲隱藏在您需求背後的陷阱非常複雜。 –

-1

我提出以下解決方案: 新表

create table room_count(room_id NUMBER primary key, cnt number); 

功能遞增計數自治事務訂單:

:new.room_order := int_room_cnt(:new.room_id); 
+0

非常感謝。 – Khoa